abar

abar

In-memory cache using Agent as as DDoS protection?

Hey all,

I’m trying to build a low-cost website serving a catalogue of items, with standard options of viewing/filtering said items. It is expected that a catalogue itself will be queried often, but rarely updated. It is also a requirement that the website is resilient against DDoS attacks and other script-kiddie-level threats.

Given the requirements (and, let’s be honest, my shallow level of Erlang/Elixir ecosystem knowledge), I was wondering if I can use Agent module to serve as an in-memory cache:

  1. Load whole db table into agent’s state as a list (or map of id → item);

  2. Whenever a user requests a page, get the table from the Agent’s state, and filter by whichever items are needed;

  3. In case of an update - reload table, replace the Agent’s state.

I read about immutability in Elixir and assumed that this would be an improvement compared to making calls to the DB each time, since copied/filtered lists and maps will still point to the same immutable list.

Then I tested both approaches locally by holding down the “F5” button and saw that memory usage goes up either way.

By now, I have read about “share-nothing concurrency” and realized that copying the whole table with the response between processes is probably not the best way to go. And while I can change Agent module to accept a filter and return only requested items (and spawn a bunch of them for good measure) - I wonder if the whole setup even makes sense in practical terms?

Maybe there’s already a module/library that does what I need, or maybe I should stop overthinking, put my server behind DDoS protection by something like Cloudflare, and call it a day?

I would be grateful to hear a hint from someone who has experience in actually deploying something to a live audience.

Marked As Solved

AstonJ

AstonJ

Some great tips in the posts above!

As Ben mentioned you will generally want multi-layered protection to be effective against DDoS attacks. So enabling your firewall and installing something like sshguard or fail2ban, using rate-limiting on the server level so requests are blocked before they touch your app (with something like HAProxy) and then rate limiting in your app and caching if possible.

The most efficient way to block attacks will be at the firewall level, followed by the proxy/load balancer (HAProxy), followed by your app (most expensive in terms of resources required - so block attacks before they hit your app whenever possible!)

You’ll then need to monitor the server and if you are getting attacked employ measures to mitigate them… but all that can be a lot so as you mentioned yourself many will opt to use a WAF like Cloudfare.

Whether you use Cloudfare or not you’ll want to ensure you harden your server, but again, it is a fairly big topic. The firewall with something like sshguard or fail2ban, changing SSH ports, removing root-login with password, etc, is a good place to start. Alternatively (and if this is commercial project) you could just get a managed server* and they should take care of a lot of it, or if this is a personal/hobby project you could start with a cloud provider like Digital Ocean because they have lots of set-up and administration guides that should help.

*When I started out we first had managed servers for a few years, then after I felt comfortable we moved to un-managed. So don’t feel like you have to dive straight into the deep end.

Also Liked

al2o3cr

al2o3cr

Consider something like Cachex which does all the things you’re thinking of and a bunch more.

benwilson512

benwilson512

Author of Craft GraphQL APIs in Elixir with Absinthe

Strong agree.

Really you want a two layer defense:

  1. Making your app fast is good, and things like cachex will help if you have cachable items.

  2. For true DDOS protection you really want to shield from that at a higher layer like the load balancer or CDN. If you have highly cacheable items a CDN can be quite helpful too, in particular if you have highly cacheable items consider just having the CDN front that too.

dimitarvp

dimitarvp

Or go to Cloudflare. You can get very far with DDoS protection before having to pay.

Last Post!

AstonJ

AstonJ

One other thing I’d add is that server specs can help too - the more powerful a server the better it will be able to process requests and deal with attacks to help prevent the server going down (especially when it comes to layer 7 attacks). When an attack is ongoing I’ve seen HAProxy use significant resources, far more than it normally would, from barely hitting 1% in normal use to 50% during an attack. More memory and SSDs can help too.

However, try not to worry or overthink it. If you’re just starting out a managed server or providers like Digital Ocean are are great place to start as they will take care of most things on the server side (or provide set-up guides to help you) leaving you to focus on your app, where you’d consider the things you already are: caching, rate-limiting, optimising queries… and of course using a language that is resilient and scalable like Elixir :003:

Where Next?

Popular in Questions Top

minhajuddin
I have seen a lot of code which picks the first element from a list using Enum.at(0) instead of List.first. Is there a reason why people ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
Lily
In templates/appointment/index.html.eex: <%= for appointment <- @appointments do %> <tr> <td><%= appoi...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
dblack
I’ve got an issue with an app and I’ve no idea of how to troubleshoot it. I’m hoping someone here might have seen something similar. I p...
New

Other popular topics Top

hariharasudhan94
Lets say I have map like this fetching from my database %{"_id" => #BSON.ObjectId<58eb1a7a9ad169198c3dXXXX>, "email" => ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New
aadeshere1
I have a another noob question about loop. Since elixir is immutable, while loop is not directly possible. total = 10 while total != 0 ...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New

We're in Beta

About us Mission Statement