Part 8: Production Patterns¶
Configure memory limits, health check tuning, backup strategies, and versioned deployments for running your todo app in production.
What you'll learn¶
- Setting memory limits per service — and why
cpudoes nothing - Tuning health checks for Spring Boot startup times
- How a failed deploy is contained, and how to roll back
- Database backup strategies
- Rolling back to a previous version with optional database restore
- Cleaning up applications
What you'll need¶
- A full deployment from Part 7 (or any earlier part)
Resource limits¶
Set a memory limit on each service so one cannot consume all of a host's memory:
database:
enabled: true
redis:
enabled: true
deploy:
- name: backend
container: backend
port: 8080
resources:
memory: 512m
health_check:
path: /health
- name: frontend
container: frontend
type: spa
command: 'nginx -g "daemon off;"' # serves the built bundle from a container
spa_root: /usr/share/nginx/html
port: 3000
resources:
memory: 128m # never below 32m for type: spa
health_check:
path: /
- name: auth
container: auth
port: 8081
resources:
memory: 512m
health_check:
path: /health
- name: worker
container: backend
command: "java -jar app.jar --worker.enabled=true"
resources:
memory: 512m
resources.memory needs a unit suffix
Write 512m, 1g or 262144k. A bare number is interpreted as bytes, so memory: 512 gives the container 512 bytes and it dies instantly. 512mb is not a recognised suffix either — use 512m.
resources.cpu is accepted but does nothing
The schema parses a cpu: value without complaint, and no code path ever applies it. It is not a CPU limit and setting it changes nothing. Omit it. Memory is the only resource AppMecca actually enforces on a container.
Java memory sizing
Java applications need headroom for the JVM beyond the heap. A Spring Boot app using 256 MB of heap typically needs a 512 MB container limit. Anything JVM-shaped below 512m produces a validation warning, because JVM runtimes routinely get killed during startup at the platform's 128 MB default. Set the heap explicitly with -Xmx384m in the entrypoint if you need precise control.
SPA memory floor
A type: spa service with resources.memory below 32m is a hard error, not a warning. Below that the nginx worker is killed silently while the master survives, and the service serves errors with nothing obviously wrong.
Health check tuning¶
Spring Boot apps can take 10-30 seconds to start, especially with JPA entity scanning and Flyway migrations. Tune the health check to avoid false failures:
deploy:
- name: backend
container: backend
port: 8080
health_check:
path: /health
interval: 15
timeout: 10
healthy_threshold: 2
unhealthy_threshold: 8
startup_timeout: 300 # seconds allowed for first boot (JVM, migrations)
| Parameter | Default | Range | Description |
|---|---|---|---|
path |
/health |
— | HTTP path probed |
interval |
30 | 5-300 | Seconds between health checks |
timeout |
5 | 2-120 | Seconds before a check is considered failed |
healthy_threshold |
2 | 2-10 | Consecutive successes before marking healthy |
unhealthy_threshold |
3 | 2-10 | Consecutive failures before marking unhealthy |
startup_timeout |
120 | 30-600 | Seconds a new container gets to become healthy during a deploy |
The thresholds have a minimum of 2
Setting healthy_threshold or unhealthy_threshold to 1 is rejected at validation time. There is no retries or start_period field — unhealthy_threshold and startup_timeout are the fields that do those jobs.
startup_timeout is the one to raise for slow boots
It is the budget a brand-new container gets to pass its health check during a deploy. For a Java app running Flyway migrations on boot, 300 seconds is a reasonable starting point. Until the new container is healthy, the previous version keeps serving.
Failed deploys and rollback¶
Tune the health check so a bad deploy is caught quickly — it is the health check that decides whether a new container is allowed to take over:
deploy:
- name: backend
container: backend
port: 8080
health_check:
path: /health
interval: 15
timeout: 10
unhealthy_threshold: 8
startup_timeout: 300 # seconds allowed for first boot (JVM, migrations)
There is no auto-rollback
AppMecca does not watch an app after a successful deploy and revert it. What protects you is blue/green: the incoming container must pass its health check within startup_timeout before traffic is switched to it, so a failing deploy leaves the running version untouched and is simply marked failed.
To go back to an earlier build, redeploy its tag — see Versioned deployments and rollback below.
Ensure your health endpoint is reliable
The health check is what gates the blue/green cutover. If /health returns 500 under transient
load, a good deploy is rejected and the old container keeps serving; if it returns 200 while the
app is broken, a bad deploy is promoted. Make it check what actually matters.
Combine resources and a tuned health_check on each service in your appmecca.yaml. The resource limits and health check sections above show the individual pieces -- apply them to every deploy entry.
Database backup strategy¶
Create a backup before every production deployment. A bundle captures the database and every declared drive:
mecca app backup todo-app -d "pre-deploy $(date +%Y-%m-%d)"
mecca build trigger -g git@github.com:yourorg/todo-app.git
mecca app deploy todo-app
List recent backups and note the bundle prefix you may need:
mecca app backups todo-app
mecca app backups todo-app --json
mecca app backups todo-app -n 50 # more than the default 20
Versioned deployments and rollback¶
List available versions and deploy a specific tag. A rollback is just a
deploy that targets an older image with --no-build:
mecca build list -a todo-app # Tag column; pick a SUCCEEDED build
mecca app deploy todo-app --image-tag abc123f --no-build # Deploy a specific existing image
mecca app deploy todo-app --image-tag abc123f --no-build
If a bad deployment included a migration, restore the database from a pre-deployment bundle as a separate step — there is no combined rollback-plus-restore command:
mecca app backups todo-app # Find the bundle
mecca app restore todo-app <bundle-prefix> # Restore DB (+ drives)
Database restore is destructive
Restoring the database replaces its current contents with the backup — any data written after that backup is lost. Verify the bundle before restoring. See Rolling Back.
Monitor your app¶
mecca app show todo-app # Per-service status and URLs
mecca app stats todo-app # Live memory and CPU per container
mecca app stats todo-app --history # Daily aggregates
mecca status todo-app # Service health and uptime
mecca status incident # Recent incidents
For deployment troubleshooting, mecca debug gathers configured variables, recent deploy errors, per-service health and resolved URLs in one shot:
Full application cleanup¶
Delete an app and everything it owns — the database (backed up, then dropped), the built images in AppMecca's image registry, the app's build configuration, stored secrets, collected logs, and every registry row:
Irreversible
mecca app delete is a full purge and cannot be undone. mecca app unregister is the same command under a different name — it is not a lighter-weight option. To stop an app without destroying anything, use mecca app undeploy.
Production checklist¶
Before going to production, verify:
- [ ]
resources.memoryset on all services, with a unit suffix - [ ] No
resources.cpuleft in the manifest (it does nothing) - [ ] Health check
startup_timeoutaccounts for JVM startup + migrations - [ ]
healthy_threshold/unhealthy_thresholdare 2 or greater - [ ]
database.max_connectionsmatches your Hikari pool size (counted per replica) - [ ] Rollback tag identified (
mecca build list -a todo-app, plusmecca app show todo-appfor the live one) before each deploy - [ ] Database backup taken before each deploy (
mecca app backup todo-app) - [ ] Environment variables reviewed (
mecca var list todo-app) - [ ] Branch deployments cleaned up (
mecca app show todo-applists live branches)
Command reference¶
| Command | Purpose |
|---|---|
mecca build list -a <app> |
Build history — the Tag of a succeeded build is what you deploy |
mecca app show <app> |
What is running now, including the live tag |
mecca app deploy <app> --image-tag <hash> --no-build |
Deploy a specific existing image (roll back / roll forward) |
mecca app backup <app> -d "<label>" |
Create a named bundle backup (DB + drives) |
mecca app backups <app> |
List bundles |
mecca app restore <app> <bundle-prefix> |
Restore the database (+ drives) from a bundle |
mecca app stats <app> |
Live per-container memory and CPU |
mecca debug <app> |
One-shot diagnostic dump |
mecca app delete <app> [--force] |
Full app purge |
What's next¶
Congratulations -- you have completed the Java + Vue tutorial track. You have gone from a hello-world Spring Boot app to a production-ready multi-service deployment with database management, background workers, branch deployments, internal service discovery, and operational patterns.
Explore the other tutorial tracks to see how the same patterns apply with different technology stacks. The AppMecca workflow is identical regardless of whether you are deploying Python, Node.js, or Java.