Deployment Skill
Local Development Stack
Three-tier architecture:
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Frontend │────▶│ Backend │────▶│ PostgreSQL │
│ React/Vite │ │ FastAPI │ │ 16 │
│ :3000 │ │ :8000 │ │ :5432 │
└─────────────┘ └─────────────┘ └─────────────┘
Configuration Files
Copy these templates to the project root when generating deployment artifacts:
templates/docker-compose.yml— Services, volumes, health checks, env setuptemplates/Dockerfile.backend.dev— Python 3.12 + FastAPI + hot reload + dependenciestemplates/Dockerfile.frontend.dev— Node 20 + Vite + hot reloadtemplates/.env.example— All required and optional env vars documented
One-Command Start
# Start everything (builds + runs)
docker compose up
# Rebuild without cache
docker compose up --build
# Stop everything (keeps data)
docker compose down
# Stop and remove all data
docker compose down -v
Database Migrations
# Apply all pending migrations
uv run alembic upgrade head
# Create migration from model changes
uv run alembic revision --autogenerate -m "description"
# Rollback one migration
uv run alembic downgrade -1
Health Checks
Verify the stack is healthy:
# Backend health
curl http://localhost:8000/health
# Frontend loads
curl http://localhost:3000
# Database is ready
docker compose exec db pg_isready -U postgres
Gotchas
- Missing depends_on with service_healthy — If backend service doesn't specify
depends_on: { db: { condition: service_healthy } }, it will start before the database is ready and fail to connect. Always require the healthcheck condition. - Hot reload not set up — If volumes don't mount source code (e.g.,
./backend/src:/app/src), developers must rebuild the container on every code change. Specify bind mounts for both backend and frontend. - Forgotten port mappings — If
ports: ["8000:8000"]is omitted, the service runs but is unreachable from the host. Always expose the dev ports. - Database password in docker-compose.yml — Never hardcode
POSTGRES_PASSWORDin version control. Use .env files andenv_file: .envin docker-compose.yml to pull from environment. - Missing .env.example — If .env.example doesn't exist, new developers won't know which env vars are required vs. optional. Document every variable: which ones block startup (required), which have defaults, and what values are valid.
- No database health check — If postgres service lacks a healthcheck, the backend starts immediately and fails to connect if the DB is still initializing. Always include a health check with reasonable retries (5+) and timeouts.