jarvism
Best way to handle 10s or 100s of thousands of API requests?
Hello, everyone!
I have an Elixir Phoenix 1.7 app deployed to fly.io. I am receiving 10,000+ API calls at a time that I need to receive, acknowledge as quickly as possible, then do a few API calls of my own, receive the information back, do something with it, and eventually report a status for each of the incoming API requests. I ran out of memory, and OK, I know how to pay more and add memory…
But now I’m wondering about the best way to handle this. I’m only able to receive each item one at a time, so I really don’t think I have any sort of context to be able to batch calls. I’m wondering if ETS is a good solution for tracking the status of each API call, or should I look into setting up a queue? This obviously is not my expertise, and I’m new to Elixir and Phoenix on top of that.
I would greatly appreciate insights from people who know better and have more experience.
Thank you so much!
Marked As Solved
dimitarvp
So, looking at your response it seems that you don’t have to immediately respond with the results.
So that’s very good. Elixir with Phoenix (or only with Plug) can handle many thousands of such requests per second. We’re talking 50k rps or more, depending on the node you’re running the app on.
And since you don’t want to lose any running tasks then I think Oban is your best bet if you are looking at building this quickly.
While I would almost always recommend getting your hands dirty and learning – because such way of learning leaves lasting memories – in this case it seems you’re leaving money on the table if you don’t deliver this soon, correct?
If so, you’re also likely better off contacting someone on this forum (or from your network) to help you construct this and pay them an appropriate consultant / programmer fee (though your company should fund this but it’s unclear if that won’t involve too much bureaucracy).
EDIT: Thinking about this a bit more, if you opt for storing your tasks in RabbitMQ or Kafka – so as to avoid overwhelming your DB pool when the upstream CMS starts sending you tons of requests, which sadly is a legitimate worry – then you might get away with your homegrown solution i.e. (1) accept request, (2) store it in RabbitMQ / Kafka, (3) respond with OK and later (4) have background workers pick up the tasks from the message queues.
Also Liked
sorentwo
Building something ad-hoc from various tools like GenStage, Stagger, Broadway, RabbitMQ, etc., would certainly work and could be an excellent learning opportunity. From a contrasting view, as some people have mentioned, you could do this with Oban starting now and scale into the 100/k range with little effort (many businesses are processing 10s of millions of Oban jobs daily).
Here are some things to consider (disclaimer, I’m entirely biased and not saying it’s the only way
):
- Horizontal scaling. Ingesting and handling that many events will require more than one system. Tools like GenStage are bound to a single node, meaning you’ll need a centralized queue to scale out. Oban solves this.
- Partitioning. You have events coming from distinct users without any pre-defined batching. To effectively de-dupe and process those events, you’ll need your consumers to process events in arbitrary groups. Oban’s partitioned global limits and chunks solve this.
- Fairness. Bursty or more active clients can drown out less active clients and prevent them from being processed in a timely manner. To combat that, you’ll want to rate-limit events by the client in some way. Oban’s partitioned rate-limiting solves this.
- Retries. Sometimes, event processing will fail, and you don’t want to lose the events you were working on. You’ll need a retry mechanism and the ability to figure out what’s wrong. Oban’s retries, error reporting, and telemetry integration solve this.
- Observability. What’s your throughput? Where are your bottlenecks? Are there errors causing this? Oban’s telemetry integration, logging, and the Web dashboard solve this.
Toss in pausing, scaling, testing, graceful shutdown, and the fact that you already have Postgres running, and Oban has a lot going for it.
sorentwo
The article One Million Jobs a Minute with Oban should cover the baseline.
Separately, watch out for a Scaling guide in the official docs in the next week or so.
dimitarvp
Since there still seems to be some confusion, let me try my hand at clarifying:
Elixir is absolutely great, almost perfect, for the scenario you are outlining.
The problem however stems from your steep requirements:
-
Raw speed. if you want every single request that comes to your app to be served in a timely basis (5-30s), and when we’re looking at 6-7 digits of requests per second, this becomes difficult even for uber-fast languages like Rust (and with some tuning, Golang). Not to mention the load balancers you need to put in front of all this since a single node can only occupy as much as ~60k network ports (there are workarounds but… long topic).
-
Persistence. You can easily spawn a million Elixir processes each serving a single request (or pertaining to a single object or batch of objects) and it is practically the best runtime environment on the planet to handle this… BUT… if your VM node goes down, all these spawned tasks will disappear. If that’s undesirable then you should use Oban. And when persistence and atomicity get involved then you’re looking at drastically reduced throughput of requests (tasks) per second.
The part from the picture that I am still missing is this: are you supposed to receive normal HTTP requests and respond within, say, 5-30 seconds to each request? Or are your API endpoints simply supposed to ingest data coming from the outside (in the shape of requests), store them and eventually process them and send responses… somewhere else, not in a HTTP response?
I couldn’t get that part from your comments, and that detail can change the recommended solution quite a lot.
Last Post!
sorentwo
The article One Million Jobs a Minute with Oban should cover the baseline.
Separately, watch out for a Scaling guide in the official docs in the next week or so.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #elixirconf-us
- #advent-of-code
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #hex









