Skip to content

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 cpu does 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:

mecca debug todo-app
mecca debug todo-app --json

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:

mecca app delete todo-app
mecca app delete todo-app --force   # Skip confirmation, auto-undeploy

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.memory set on all services, with a unit suffix
  • [ ] No resources.cpu left in the manifest (it does nothing)
  • [ ] Health check startup_timeout accounts for JVM startup + migrations
  • [ ] healthy_threshold / unhealthy_threshold are 2 or greater
  • [ ] database.max_connections matches your Hikari pool size (counted per replica)
  • [ ] Rollback tag identified (mecca build list -a todo-app, plus mecca app show todo-app for 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-app lists 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.