silviurosu

silviurosu

I have a dilema that I would like to hear your input on:
We have a server that serves a decently high rate of api calls and needs to stay as fast as possible.
In our business logic there are a bunch of background jobs that need to run and that are not time critical, there is no big rush in finishing them, like orders export, notifications, scheduled tasks like generating invoices, etc. They can take significant CPU though.
Currently we run them via Oban inside the same servers that serve the API and the rest of our business logic. My concern is that they can impact performance and starve the CPU which will affect the performance of the API’s and websockets.

Would be more appropriate to create another umbrella app or something that I can pack differently via mix releases and deploy to a separate server that has no rush in finishing the tasks and it’s not a problem if saturates the CPU?
How do you guys do it??

Showing Posts 1 to 10

krasenyp

krasenyp

There are a few questions that need to be answered. What does “a decently high rate of api calls” mean? Do the API request handling put high load on the CPU relative to RAM? It usually doesn’t but history has seen many different cases. Maybe a load/stress test can show how much requests and background tasks your service can take?

D4no0

D4no0

There are 2 ways to go about this:

  1. Rate limit the processing - use the Oban rate limiter (not sure how it works and it seems you need Oban pro) or Broadway or Genstage, this will save a lot of complexity and time in general.
  2. Use RabbitMQ or built-in erlang message passing from node to node to pass events to another server that will do the processing. In this case you need to decide whether losing events is acceptable and a strategy of what happens when something goes down, much more complex compared to the first solution.
dimitarvp

dimitarvp

I get where you are coming from and I am a paranoid prepper myself but I’d advise you to measure first before going into a potential rabbit hole.

silviurosu

silviurosu OP

I agree that I may be getting to a potential Rabbit hole. I will leave things as is for now and try instead to add more metrics and limit background workers concurrency to a certain level.

Ankhers

Ankhers

Something to remember when you are developing in the BEAM: The scheduler is preemptive, operating on a time-sharing principle. This means that the VM will actually pause long-running processes (such as your background jobs) from time to time in order to let other processes (such as your web requests, which should be very short-lived) have a turn. This is done by allocating a specific number of reductions (function calls) to each process, after which the scheduler will switch to the next process in the queue.

The primary advantage of this approach is that it ensures every process gets some CPU time even under very heavy load, promoting fairness and responsiveness. It is not to say that your background jobs will have no negative impact on the time it takes to finish processing a request, but it’s not nearly as detrimental as a cooperative scheduler, which would not pause processes and just lets them run until they finish what they are doing. This can lead to issues like process monopolization, where a single process takes over the CPU and doesn’t allow other processes to run.

In Erlang’s system, the preemptive scheduling helps in distributing resources evenly, maintaining system responsiveness, and avoiding the risk of any single process overwhelming the system. This design reflects Erlang’s focus on concurrency, fault tolerance, and distributed computing, making it particularly suitable for scalable and highly available systems.

engineeringdept

engineeringdept

We run our Oban workers on separate VMs (Heroku dynos) that don’t serve web traffic. While the BEAM scheduler is great, it’s useful having a separate CPU/memory environment for each that can be scaled independently.

We do this by disabling the queues on the web workers with an environment variable which is read by the runtime.exs config.

silviurosu

silviurosu OP

Interesting approach. Do you have any kind of autoscale in place?
For example how do you scale your heroku dynos based on jobs in the queue.

silviurosu

silviurosu OP

I have not hear about it before. I will definitely try it.
What kind of metrics do you track?

engineeringdept

engineeringdept

No, our main bottleneck is our database and auto scaling up more dynos would just increase the load on this to the point where it had an effect on web users. Auto scaling down during quiet periods might save us some money, but it’s not a cost that’s meaningful right now.

Where Next? Top

Trending in Questions Top

RSP87
I’m working on a project that simulates the bumbl example in the programming phoenix book. It acts almost like an email client. We have a...
New
nseaSeb
Hello, I know there is an approach for handling lists that allows for optimized traversal, but I can’t recall the specific method (somet...
New
RemyXRenard
I’m seeing that a list inside a Kino.DataTable will be interpreted as a charlist, even if the Kino.configure() is set to charlists: :as_l...
New
brecabral
Documentation While reading the Scoped Routes section, I noticed that the documentation currently refers to a problem without explainin...
New
velrest
So my question is quite simple and i have found no conclusive answer on forum, google or AI. Should we use :erlang.float for Integer to ...
New
samoloth
Hi, I’ve just set up an application with ash_authentication. There is only magic link strategy for now, so there is no confirmation add o...
New
FlyingNoodle
If a change or preparation module uses Ash.Changeset.get_argument/2 or Ash.Query.get_argument/2 (or any of the other get_argument functio...
New

Other Trending Topics Top

mudasobwa
I am happy to introduce the very α version of the new programming language compiled to BEAM. Welcome Cure. It has literally three kille...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
netoum
Corex is an accessible, unstyled UI component library for Phoenix that integrates Zag.js state machines using Vanilla JavaScript and Live...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews