jarvism

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

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

sorentwo

Oban Core Team

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 :wink:):

  • 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

sorentwo

Oban Core Team

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

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:

  1. 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).

  2. 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

sorentwo

Oban Core Team

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.

Where Next?

Popular in Questions Top

rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
nobody
Hi! In PHP: $_SERVER[‘SERVER_ADDR’] - in Elixir? Searched the docs for ip address and the web, no good results. Thanks!
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
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
freewebwithme
Using vs code and installed ElixirLS: support and debugger. And I got an error popped up on start up says Failed to run ‘elixir’ comma...
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

Other popular topics Top

baxterw3b
Hi guys, i’m new in the Elixir world, and i have to say, that i love it! i’m having some problem to understand anonymous functions with ...
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31494 112
New
gshaw
What is the idiomatic way of matching for not nil in Elixir? E.g., First way: defp halt_if_not_signed_in(conn, signed_in_account) when...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
AngeloChecked
What learn first? Rust or Elixir Hi Elixir community! I’m here because i want learn a new language. I’m a junior developer and mainly i ...
New
Harrisonl
We have an ECS cluster with 4 services, where each task joins a single cluster, via discovery ECS discovery service. Currently when I de...
New

We're in Beta

About us Mission Statement