Migrate to koigrid
Move your stack from AWS/Vercel/Railway/Render piece by piece — each step is reversible. Postgres migrates with near-zero downtime via logical replication (CDC), so you cut over when lag is 0.
1. Postgres
Simple: dump + restore. Near-zero-downtime: logical replication streams your source into koigrid; cut over at lag 0.
# 1) Create the managed database + get its URL koigrid db create prod --version 16 DATABASE_URL="$(koigrid db connection <id> --json | jq -r .connection.uri)" # --- Simple (dump + restore) --- pg_dump "$SOURCE_URL" | psql "$DATABASE_URL" # or: drizzle-kit migrate / prisma migrate deploy # --- Near-zero-downtime (logical replication / CDC) --- # a) on your SOURCE (e.g. RDS with rds.logical_replication=1): # CREATE PUBLICATION mig FOR ALL TABLES; # b) copy the SCHEMA to koigrid first (tables must exist): pg_dump --schema-only "$SOURCE_URL" | psql "$DATABASE_URL" # c) on koigrid (the app user has REPLICATION — no superuser needed): # CREATE SUBSCRIPTION mig CONNECTION 'postgresql://user:pass@source-host:5432/db' PUBLICATION mig; # d) watch lag → 0: SELECT * FROM pg_stat_subscription; # e) cut over (point the app at koigrid), then: DROP SUBSCRIPTION mig;
2. Storage (S3)
Your bucket already speaks S3 — copy objects with rclone or aws-cli, then repoint your client’s endpoint + keys.
koigrid storage buckets create assets koigrid storage keys # → accessKey / secretKey / endpoint (shown once) # copy objects from your old S3 (rclone remote 'koigrid' → https://s3.koigrid.com, path-style) rclone copy s3old:my-bucket koigrid:assets # then repoint your S3 client: endpoint=https://s3.koigrid.com, forcePathStyle=true, # new keys, and use the bucketName koigrid returns (not the friendly name).
3. App
Deploy from a git repo, a container image, or your local folder (--dir, no git/Docker needed). Set env vars, then a custom domain.
# from a git repo (add --repo-token for a private repo):
koigrid apps deploy web --repo https://github.com/you/app
# ...or straight from your local folder (no git, no Docker):
koigrid apps deploy web --dir ./
# env vars (invalid lines are reported, not fatal; saved even before the first deploy):
curl -X POST $API/apps/<id>/env -H "Authorization: Bearer koi_KEY" \
-d '{"env":{"DATABASE_URL":"...","API_KEY":"..."}}'
# custom domain + automatic TLS:
koigrid apps domains web app.yourdomain.com4. Cron jobs
Your EventBridge/cron endpoints become HTTP jobs — koigrid hits the URL on schedule with your secret header.
# an EventBridge/cron endpoint → an HTTP job (koigrid calls the URL on schedule): koigrid jobs create nightly --schedule "0 3 * * *" \ --url https://app.yourdomain.com/api/cron/report --header "x-cron-secret: $SECRET" # ...or a container job: koigrid jobs create backup --schedule "0 2 * * *" --image alpine --command "sh -c '…'"
5. Cutover
Point DNS at koigrid with a rollback ready. Bandwidth is included and flat — no egress surprise on the way out of AWS.
# point your DNS at koigrid, keep the old stack ready to roll back. # bandwidth is included + flat — no egress bill on the way out of AWS.