Express + BullMQ Workers¶
Node.js/Express application with BullMQ for background job processing, running three services from one Docker image.
Overview¶
| Tech Stack | Node.js / Express + BullMQ |
| Services | 3 (api + worker + scheduler) |
| Database | PostgreSQL (managed) |
| Cache | Redis (managed) |
| Pattern | Background workers, memory limits |
The appmecca.yaml¶
containers:
- name: app
dockerfile: Dockerfile
context: .
deploy:
- name: api
container: app
port: 3000
health_check:
path: /health
resources:
memory: "512m"
- name: worker
container: app
command: "node worker.js"
resources:
memory: "256m"
- name: scheduler
container: app
command: "node scheduler.js"
resources:
memory: "128m"
database:
enabled: true
redis:
enabled: true
Key Concepts¶
Memory Limits (resources.memory)¶
resources.memory sets a hard memory ceiling for each service's containers. This matters for
worker services whose needs differ from the API's — the scheduler here only runs periodic
maintenance, so it gets the least.
The unit suffix is mandatory
Write 512m, 256m, 1g — a suffix of k, m or g (case-insensitive). A bare
number is interpreted as bytes, so memory: 512 means 512 bytes and the container will
not start. 512mb is not a recognised form either.
resources.cpu does nothing
The schema accepts a cpu: key, but no part of the platform applies it — it is never
passed to the container runtime. Do not rely on it to shape CPU allocation. Memory is the
limit that is actually enforced.
Three Services from One Image¶
All three services (api, worker, scheduler) use the same Docker image (app). The worker and scheduler override the default CMD with custom command values. Only the API has a port -- the others are portless services.
BullMQ Queue¶
BullMQ provides reliable job processing with Redis. Tasks are enqueued by the API, processed by the worker with concurrency control, and the scheduler handles periodic cleanup of stale tasks.
Step-by-Step Deployment¶
1. Register the app¶
2. Build¶
3. Deploy¶
4. Verify¶
mecca queue status takes the action ID printed when you deployed. To look up the app —
and its exact URL for your group — use mecca app show:
# Create a task
curl -X POST https://express-bull-workers-api.dev.appmecca.net/api/tasks \
-H 'Content-Type: application/json' \
-d '{"title": "Test task"}'
# Check queue stats
curl https://express-bull-workers-api.dev.appmecca.net/api/queue/stats
Only the api service has a port, so only api gets a URL. The service name is always part
of the hostname.
What's Next¶
- Django + Celery Tasks -- Python version with Celery
- Spring Boot Workers -- Java version
- Ruby + Sidekiq Workers -- Ruby version