flowardΒ·vibes
Home / 10 β€” Migrating an Existing App 4 min read

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.md in 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

  1. Remove all secrets from the code and config files (Phase 2 gave them env-var homes).
  2. Scan history: git log -p | grep -iE 'password|api[_-]?key|BEGIN.*PRIVATE KEY|AKIA[0-9A-Z]{16}'
  3. Any secret that ever touched Git history is compromised β€” rotate it now (tell DevOps). Cleaning history is optional; rotation is not.
  4. Add .env to .gitignore and dockerfiles/.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.