← Back to blog

Splitting Background Jobs Off Your Web Server

Maria Ilinca Bostan

There is a stage every growing application reaches where page loads get slow at seemingly random moments. Nothing in the request path changed. What changed is that the same machine is now generating a monthly report, resizing images, sending a mailing list, rebuilding a search index and answering visitors, all at once, and the visitors lose.

The fix is not a bigger server. It is a second, smaller one that does nothing but background work. This is how to split it, how to size both halves, and what it costs.

The symptoms that mean it is time

  • Response times spike on a schedule, usually on the hour or overnight.
  • A long job and the web process fight over memory, and the out of memory killer picks a winner you did not choose.
  • A deploy restarts the application and kills a job halfway through.
  • Two copies of the same scheduled task overlap because the last run had not finished.
  • You have started avoiding running a heavy task during the day, which is a scheduling workaround for a capacity problem.

The shape of the split

Three pieces, and the middle one is what makes it work.

  1. A web machine. Handles requests only. Its job is to accept a task and answer immediately.
  2. A queue. Somewhere durable that both machines can see. A dedicated queue service, or a table in your existing database if the volume is modest. Durable matters more than fast for most applications, because a lost job is worse than a slow one.
  3. A worker machine. Pulls tasks and runs them. It can be restarted, resized or replaced without anybody noticing, which is the real prize.

Keep both machines in the same city. Every task handoff and every database query from the worker pays the round trip, and a worker in Bucharest talking to a database in Frankfurt pays 10 ms on every single query. Our five virtual machine cities are Frankfurt, Amsterdam, Vienna, Warsaw and Bucharest, so there is always a local pair.

Traffic between machines in the same city crosses the network rather than a private cable, so put the queue and database connections inside an encrypted tunnel between the two rather than opening a database port. A WireGuard link between two virtual machines takes a few minutes.

Sizing both halves

Workers want cores and memory. Web machines want less of both than people think, once the heavy work has left.

SetupWebWorkerMonthly in Frankfurt or Vienna
Small application, image resizing and mailPulse, 4 GBPulse, 4 GB€19.00
Busy application, reports and index rebuildsCore, 8 GBForge, 16 GB€45.00
Heavy processing, video or large exportsCore, 8 GBApex, 24 GB€64.00

In Bucharest the same three rows are €13.00, €29.00 and €44.00, because Romania is our base price with no location fee. The full grid for all six plans and all five cities is in the price by location breakdown, and unmetered traffic on both machines means the chatter between them is never a billing line.

Where hourly billing genuinely wins

Background work is bursty by nature, which is exactly the shape hourly pricing suits. The rate is the monthly price divided by 720, plus the location fee divided by 720.

  • A one off backfill. Reprocessing two years of records is a Titan for six hours, which in Frankfurt is €0.70. Delete it when the queue is empty.
  • A seasonal peak. A second worker for the ten days around a launch, on a Forge in Vienna at €0.0389 an hour, is €9.34 if it runs the whole time.
  • A migration weekend. An extra machine to chew through an import while the permanent worker keeps the normal queue moving.

Two rules. Deleting the machine is what stops the charges, because a powered off machine still holds its disk and its address. And the permanent worker is an always on machine, so it belongs on a monthly, quarterly or annual cycle, since 720 hourly units cost exactly one month.

The five mistakes that make this painful

  1. Two schedulers. If both machines run the cron entries, everything happens twice. One machine schedules, or every task takes a lock before it starts.
  2. Jobs that are not safe to retry. A worker will be killed mid task eventually. Tasks should be safe to run twice, and anything that sends money or email needs its own record of what it already did.
  3. Shared local files. If the web machine writes an upload to its own disk and the worker expects to find it, the split breaks quietly. Pass content through the queue, or keep uploads somewhere both can reach.
  4. No visibility into queue depth. A worker that has silently stopped looks exactly like a quiet day. Alert on the queue growing and on the worker going silent. Our note on monitoring from another city covers where those alerts should live.
  5. Forgetting the database is now the shared bottleneck. Two machines hammering one database concentrates the load rather than spreading it. The sizing rules in database servers on a VPS apply to the sum of both.

What the web machine gets back

Predictability, which is the entire point. Response times stop depending on what else the machine felt like doing. You can restart workers during the day. You can resize the worker for a heavy month and put it back afterwards. And when the worker falls over, the site stays up with a slightly stale queue, which is a far better failure than a slow site.

Where to start

Move one task. The heaviest, most annoying scheduled job, onto one small machine in the same city, with a lock so it cannot overlap. Measure your response times for a week. Then move the rest. Plans are on the VPS page, the ordered list of performance work is in optimising VPS performance, and the wider growth path is in scaling from one server to many.

Ready in under a minute

Deploy your first server now.

No contracts, no minimums. Start on an Ion KVM VPS at €0.0063 an hour and move to a monthly bare-metal server the day you outgrow it.

$ voxa deploy --plan ion --location amsterdam

KVM VPS billed hourly, capped monthly · Dedicated billed monthly · No setup fee

Included on every plan
Free IPv4 + IPv6
Every VPS
Unmetered traffic
1–10 Gbps
DDoS mitigation
2.5 Tbps
Root / IPMI access
Included
Setup fee
€0.00
Minimum term
None