A Laravel queue worker that actually stays alive on a R 100/month VPS
Supervisor, sane retry config, OOM guards and a Pushover heartbeat. The exact set-up we put on every R 100/month VPS we deploy a Laravel job runner to.

Most "how to run Laravel queues in production" tutorials assume you're on a beefy box. Here's the minimal-resources version: a single Hetzner CX21 or similar SA-hosted VPS, ~2GB RAM, running web + queue together.
Supervisor config
We use Supervisor (not systemd directly, because of the per-process restart guarantees). One worker group per critical queue: default, ai, mail. AI jobs sit on their own queue so a slow OpenAI call doesn't block a contact-form email.
[program:sitect-queue-ai]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/sitect/artisan queue:work --queue=ai --tries=3 --backoff=30 --max-time=3600 --memory=192
autostart=true
autorestart=true
user=www-data
numprocs=1
stopwaitsecs=60
--max-time=3600 kicks the worker after an hour so memory leaks (yours or upstream's) don't accumulate. --memory=192 is a hard ceiling.
A heartbeat to Pushover
A scheduled task every 5 minutes that fires a small ping to a heartbeat endpoint. If two consecutive pings don't arrive, Pushover wakes us up. Free tier of healthchecks.io works fine too.
Why this matters for AI workloads
AI jobs are unusual: they're long-running (10–30s), expensive (R0.02–R1 each) and they fail in interesting ways (rate limits, timeouts, JSON parse errors). Without a healthy worker, leads silently sit in ai_qualifying status forever. Get this right early.
Comments (0)
No comments yet — be the first to share a thought or ask a question.