Skip to content

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

mecca register git@gitlab.com:appmecca-sample-apps/express-bull-workers.git \
  -e dev

2. Build

mecca build trigger \
  -e dev \
  -g git@gitlab.com:appmecca-sample-apps/express-bull-workers.git

3. Deploy

mecca app deploy -e dev express-bull-workers

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:

mecca app show express-bull-workers -e dev
# 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