10 β Migrating an Existing App
Who this is for: you already built a vibe-coded app on your own β before finding this guide β and now want the DevOps team to host it. You don't start over. You retrofit, in a safe order, and keep your app working the whole time.
Give your AI assistant this prompt: "I have an existing app that must be migrated to my company's hosting rules. Read
guides/10-migrating-existing-apps.mdin the reference repo and run the audit in Phase 0 against my code, then walk me through the phases one by one. Do not rewrite the app β retrofit it."
Phase 0 β Audit (do this first, change nothing yet)
Ask your AI assistant to check your repo against each item and produce a gap list:
| Check | Rule | Where it's defined |
|---|---|---|
| Folder structure | .github/workflows/, dockerfiles/, kubernetes/, source/ |
guide 02 |
| Database engine | PostgreSQL only | guide 06 |
| Secrets in code or Git history | zero β git grep -iE 'password|secret|api[_-]?key|token' and check history too |
guide 07 |
| In-memory sessions / local file writes / in-process cron | none β must survive 2+ replicas | guide 08 |
| Dockerfile | exists, multi-stage, non-root, Linux | guide 03 |
| Health endpoints | /healthz + /readyz |
guide 08 |
| SIGTERM handling | graceful shutdown | guide 08 |
| Env-var-only config | no hardcoded hosts/ports/credentials | guide 07 |
The phases below are ordered so each one is a small, safe, individually committable change. Don't reorder β later phases assume the earlier ones.
Phase 1 β Restructure folders
Move your app code into source/ (including package.json / requirements.txt), then fix any paths that assumed the old layout. Create the empty dockerfiles/ and kubernetes/ directories. Run your app locally to confirm nothing broke.
Phase 2 β Externalise configuration
Replace every hardcoded config value (ports, hostnames, credentials, feature flags) with environment variables with sensible defaults for local dev. Create source/README.md documenting every variable (guide 07's table format) and a .env.example with placeholders.
Phase 3 β Secrets cleanup
- Remove all secrets from the code and config files (Phase 2 gave them env-var homes).
- Scan history:
git log -p | grep -iE 'password|api[_-]?key|BEGIN.*PRIVATE KEY|AKIA[0-9A-Z]{16}' - Any secret that ever touched Git history is compromised β rotate it now (tell DevOps). Cleaning history is optional; rotation is not.
- Add
.envto.gitignoreanddockerfiles/.dockerignore.
Phase 4 β Database
- Already on PostgreSQL: make sure the connection uses
DB_HOST/DB_PORT/DB_NAME/DB_USER/DB_PASSWORD, a connection pool, and a concurrency-safe migration tool (guide 06). Done. - On MySQL/MongoDB/SQLite/anything else: this is the biggest step β plan it with the DevOps team before writing code. Typically: introduce PostgreSQL via your ORM/driver, port the schema with proper migrations, write a one-off data migration script, verify, then remove the old engine. Do this as its own PR; don't mix it with other phases.
Phase 5 β Statelessness retrofit
Fix everything the Phase 0 audit flagged from guide 08:
- Sessions in memory β move to PostgreSQL-backed sessions or signed stateless tokens (JWT).
- Files written to local disk β external file store (ask DevOps for the approved option).
- In-process cron/background jobs β job queue, Kubernetes CronJob (ask DevOps), or a PostgreSQL advisory lock so exactly one replica runs the job.
Phase 6 β Health endpoints & graceful shutdown
Add GET /healthz (200 whenever the process is alive, no DB check) and GET /readyz (200 only when ready, incl. a SELECT 1 DB check), plus the SIGTERM handler β copy the patterns in guide 08.
Phase 7 β Containerise
Write dockerfiles/Dockerfile (+ .dockerignore) per guide 03. Verify:
docker build -f dockerfiles/Dockerfile -t migrate-test .
docker run --rm -p 3000:3000 migrate-test # starts with env vars only
docker run --rm migrate-test whoami # not root
Phase 8 β Kubernetes manifests & pipeline
Add kubernetes/deployment.yaml, service.yaml, configmap.yaml (guide 04) and .github/workflows/ci.yml (guide 05) with the DevOps-provided values left as marked placeholders.
Phase 9 β Final gate
Run the full checklist in guide 09. When it's green, submit to the DevOps team like any new app (same SLA: 5 business days end-to-end). Mention in your submission that this is a migrated app and list anything from Phase 4/5 you'd like DevOps to double-check.
Common traps
- Doing phases out of order β e.g. containerising before config is externalised bakes secrets into images.
- Rewriting instead of retrofitting β the goal is compliance, not a new app. Resist your assistant's urge to "improve" unrelated code.
- Skipping rotation because the secret was "only briefly" in history. Rotate it.
- A giant single PR. One phase = one PR keeps review fast and rollback trivial.