Spring Boot Workers¶
Java/Spring Boot application with Redis-backed task queue, demonstrating two services from one Docker image.
Overview¶
| Tech Stack | Java 21 / Spring Boot + Redis |
| Services | 2 (api + worker) |
| Database | PostgreSQL |
| Cache | The managed Redis cache |
| Pattern | Background workers, conditional activation |
The appmecca.yaml¶
containers:
- name: app
dockerfile: Dockerfile
context: .
deploy:
- name: api
container: app
port: 8080
health_check:
path: /health
startup_timeout: 300
resources:
memory: "512m"
- name: worker
container: app
command: "java -jar app.jar --app.worker.enabled=true --server.port=0"
resources:
memory: "512m"
database:
enabled: true
redis:
enabled: true
JVM services need resources.memory
Both services run a JVM, so both declare 512m. The platform default is
128 MB, which a Spring Boot process exhausts during startup — the container
is killed with exit code 137 before it ever serves a request. Validation
warns you about this when it can see a JVM-shaped command:, but it cannot
see inside your Dockerfile's CMD, so set it explicitly on every JVM
service.
The unit suffix is required. 512m and 1g are valid; a bare 512
means 512 bytes and 512mb is not a recognised form.
Key Concepts¶
Conditional Worker Activation¶
The worker uses Spring's @ConditionalOnProperty annotation. The TaskWorker bean only starts when app.worker.enabled=true is passed via the command override. This means the API service never accidentally processes tasks.
Redis as a Simple Queue¶
Instead of a dedicated message broker, this app uses a Redis list as a task queue. The API pushes task IDs with LPUSH, and the worker pops them with BRPOP. This is simpler than using a full message broker for basic use cases.
Step-by-Step Deployment¶
1. Register the app¶
2. Build¶
3. Deploy¶
4. Verify¶
The worker is portless, so it has no URL. Check it with its logs instead:
What's Next¶
- Express + BullMQ Workers -- Node.js version with 3 services and resource limits
- Django + Celery Tasks -- Python version with Celery