Migra a koigrid
Mueve tu stack desde AWS/Vercel/Railway/Render pieza a pieza — cada paso es reversible. Postgres migra casi sin downtime con replicación lógica (CDC): haces el cutover cuando el lag es 0.
1. Postgres
RESTORE GESTIONADO (lo más fácil): sube tu dump y koigrid lo importa — POST /databases/:id/restore-dump/upload-url {gzip:true} → PUT del .sql.gz → POST /databases/:id/restore-dump {dumpKey}, o koigrid db restore-dump <id> --file dump.sql --wait (el CLI comprime y sube en streaming). Pre-siembra las extensiones (arregla el desajuste de extensions.vector de Supabase), falla rápido con la CAUSA RAÍZ, es atómico (un fallo deja la BD intacta, así que el reintento da la misma causa), conserva tu dump para que reintentar no cueste re-subirlo, y da la propiedad a tu rol de app para que los datos se lean desde el primer momento. Alternativa manual: dump + restore. Casi sin downtime: la replicación lógica vuelca tu origen en koigrid en streaming; cutover con lag 0. Para un restore grande, conéctate al puerto DIRECTO de escritura (no al pool de PgBouncer) — el pooling en modo transacción rompe COPY y los restores largos.
# 1) Create the managed database — match your SOURCE major version (14-17) to avoid dump mismatches
koigrid db create prod --version 17
DATABASE_URL="$(koigrid db connection <id> --json | jq -r .connection.uri)"
# --- Simple (dump + restore) ---
# For a BIG restore, connect to the DIRECT write port (connection.writeUri), NOT the pool: transaction
# pooling breaks COPY and long restores (missing tables/indexes).
pg_dump "$SOURCE_URL" | psql "$DATABASE_URL" # or: drizzle-kit migrate / prisma migrate deploy
# ex-Supabase? install extensions into their schema:
# POST /databases/:id/extensions {"name":"uuid-ossp","schema":"extensions"} (koigrid does it as superuser)
# --- 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;
# --- After migrating: automatic password rotation (AWS Secrets Manager rotation substitute) ---
# ZERO-DOWNTIME dual-role rotation. One-time: switch the pooler to reloadable mode, then schedule:
koigrid db rotation <id> migrate # brief reconnect, once
koigrid db rotation <id> set --interval 30 # rotate every 30 days (or: koigrid db rotation <id> rotate)
# apps wiring DATABASE_URL='${{db.<name>.DATABASE_URL}}' auto-redeploy with the fresh password.2. Almacenamiento (S3)
Tu bucket ya habla S3 — copia los objetos con rclone o aws-cli y reapunta el endpoint + claves de tu cliente.
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
CERO cambios de código: koigrid soporta virtual-hosted-style (bucket.s3.koigrid.com), así que el AWS SDK estándar funciona tal cual — pon AWS_ENDPOINT_URL_S3 + tus claves como variables de entorno y deja tu código igual:
# Your app's S3 code stays EXACTLY as-is. Just set env vars: AWS_ENDPOINT_URL_S3=https://s3.koigrid.com AWS_ACCESS_KEY_ID=<from koigrid storage keys> AWS_SECRET_ACCESS_KEY=<from koigrid storage keys> AWS_REGION=us-east-1 # any value; koigrid is region-agnostic # koigrid supports virtual-hosted-style (bucket.s3.koigrid.com), so the standard # new S3Client() works with no forcePathStyle and no code change. Use the bucketName # koigrid returns (koi-<org>-<name>-xxxx) as the Bucket.
3. App
Despliega desde un repo git, una imagen de contenedor, o tu carpeta local (--dir, sin git ni Docker). Fija env vars y luego un dominio propio. El CDN está activo por defecto y cachea tu HTML en el edge honrando el Cache-Control (envía s-maxage=N; el ISR de Next.js ya lo hace) — latencia de borde estilo CloudFront, sin config extra; las apps protegidas y los previews nunca se cachean en el edge.
# 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
Tus endpoints de EventBridge/cron pasan a jobs HTTP — koigrid pega a la URL según el cron con tu cabecera secreta.
# 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
Apunta el DNS a koigrid con rollback preparado. El tráfico va incluido y en tarifa plana — sin sorpresa de egress al salir de 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.