EPK Migration Runbook & Rollback Plan
Source platform: Base44 (proprietary, locked-in)
Target platform: Self-hosted on Hetzner Cloud (PostgreSQL, Redis, MinIO, kubeadm K8s + Hetzner LB + DNS)
Estimated timeline: 10β11 weeks (per architecture audit)
Critical blockers: 7 requiring full reimplementation, 3 partial, 5 platform constraints
Phase 0 β Pre-Migration Setup
Prerequisites
Environment Variables (secrets)
| Variable |
Source |
Target |
HETZNER_TOKEN |
1Password / Vault |
TF_VAR_hcloud_token |
DOMAIN |
DNS zone |
epk.example.com |
DB_PASSWORD |
Generated |
PostgreSQL superuser |
REDIS_PASSWORD |
Generated |
Redis ACL |
MINIO_ACCESS_KEY / MINIO_SECRET_KEY |
Generated |
MinIO root |
JWT_SECRET |
Generated (256-bit) |
Auth service |
OAUTH_*_CLIENT_ID / OAUTH_*_SECRET |
Provider dashboards |
6 OAuth connectors |
Phase 1 β Data Export from Base44
1.1 Export Strategy
- Frontend-only export: Base44 GitHub export contains only React frontend code. Backend (DB, auth, functions, realtime) is proprietary and not exported.
- Data export: Use Base44 admin dashboard β "Export Data" (JSON/CSV per entity). For large datasets, request Base44 support for full DB dump.
- Entities to export: All inferred EPK entities from audit (users, projects, tasks, comments, attachments, subscriptions, webhooks, audit_logs, etc.).
1.2 Export Checklist
1.3 Known Limitations
- No access to Base44 internal IDs for auth users (map by email)
- Realtime subscription state not exportable β rebuild from scratch
- File attachments stored in Base44 CDN β download URLs expire in 24h
Phase 2 β Schema Transformation Scripts
2.1 Mapping Rules (MongoDB-compat β PostgreSQL + RLS)
| Base44 Type |
Postgres Type |
Notes |
ObjectId |
uuid (gen_random_uuid()) |
PK on all tables |
Date |
timestamptz |
UTC normalized |
DBRef |
uuid FK + RLS policy |
Enforce ownership |
Array<subdoc> |
JSONB column / child table |
Normalize if queried |
Binary |
bytea or MinIO object ref |
> 1MB β MinIO |
2.2 Transformation Pipeline
exports/YYYYMMDD/*.json
β
βΌ
scripts/transform/
βββ 01_normalize_ids.py # ObjectId β UUID, build ID map
βββ 02_flatten_arrays.py # Subdoc arrays β child tables
βββ 03_enforce_rls.py # Add owner_id, gen policies
βββ 04_attachments_to_minio.py # Download + upload, rewrite refs
βββ 05_validate_schema.py # pg_dump --schema-only diff
β
βΌ
staging_import/YYYYMMDD/*.sql
2.3 Script Checklist
Phase 3 β Import Validation
3.1 Staging Import Procedure
terraform -chdir=infra/terraform apply -target=hcloud_server.db -auto-approve
psql "$STAGING_DB_URL" -f schema/target.sql
psql "$STAGING_DB_URL" -f staging_import/YYYYMMDD/01_core.sql
psql "$STAGING_DB_URL" -f staging_import/YYYYMMDD/02_relations.sql
psql "$STAGING_DB_URL" -f staging_import/YYYYMMDD/03_attachments.sql
python scripts/validate_import.py --env staging
3.2 Validation Checks
| Check |
Tool |
Threshold |
| Row count per table |
validate_import.py |
Β±0.1% vs export |
| Referential integrity |
pg_dump --data-only --inserts |
0 FK violations |
| RLS policy coverage |
SELECT * FROM pg_policies |
100% tables with owner_id |
| Attachment checksums |
MinIO mc stat + DB file_sha256 |
100% match |
| Auth user mapping |
validate_import.py --auth |
100% emails mapped |
| Index usage |
pg_stat_user_indexes |
No unused indexes > 100MB |
3.3 Import Checklist
Phase 4 β DNS Cutover
4.1 Pre-Cutover (T-24h)
4.2 Cutover Procedure (T=0)
curl -sf https://candidate.epk.example.com/healthz
hcloud dns record update --zone epk.example.com --id <apex_id> --value <lb_ip>
hcloud dns record update --zone epk.example.com --id <www_id> --value <lb_ip>
for r in us eu asia; do dig @$r.epk.example.com +short; done
hcloud dns record update --zone epk.example.com --id <apex_id> --ttl 3600
4.3 Post-Cutover (T+0 to T+1h)
Phase 5 β Smoke Tests
5.1 Automated Suite (scripts/smoke_test.py)
| Test |
Description |
Timeout |
healthz |
GET /healthz returns 200 + {"status":"ok"} |
5s |
auth_login |
POST /auth/login β JWT + refresh cookie |
10s |
auth_refresh |
POST /auth/refresh rotates tokens |
5s |
oauth_google |
Full OAuth flow (headless) |
30s |
crud_project |
Create β Read β Update β Delete project |
15s |
realtime_sub |
WS connect β subscribe β receive event |
20s |
file_upload |
POST /files β 201 + MinIO object exists |
30s |
webhook_delivery |
Trigger webhook β verify signature + retry |
30s |
5.2 Manual Spot-Checks
5.3 Smoke Test Checklist
Phase 6 β Rollback Triggers & Procedure
6.1 Automatic Rollback Triggers
| Metric |
Threshold |
Window |
Action |
| HTTP 5xx rate |
> 5% |
5 min |
Auto-rollback DNS |
| p95 latency |
> 2s |
5 min |
Alert + manual decision |
| WebSocket connect failure |
> 10% |
5 min |
Alert + manual decision |
| DB replication lag |
> 30s |
2 min |
Alert + manual decision |
| Smoke test failure |
Any critical test fails |
1 run |
Auto-rollback DNS |
6.2 Manual Rollback Decision Matrix
| Scenario |
Decision |
Owner |
| Single non-critical test flaky |
Investigate, re-run |
On-call |
| Multiple critical tests fail |
Rollback immediately |
On-call |
| Data inconsistency reported |
Rollback immediately |
TL + On-call |
| Performance degrade, recovering |
Monitor 15 min, then decide |
TL |
6.3 Rollback Procedure (DNS-based, < 2 min)
hcloud dns record update --zone epk.example.com --id <apex_id> --value <base44_ip>
hcloud dns record update --zone epk.example.com --id <www_id> --value <base44_ip>
curl -sf https://epk.example.com/healthz
./scripts/notify.py --channel "#epk-migration" --text "ROLLBACK executed at $(date -u +%H:%M UTC). Base44 live."
6.4 Post-Rollback
Phase 7 β Post-Migration (T+24h to T+7d)
7.1 Stabilization Checklist
7.2 Decommission Base44 (T+7d)
Appendix A β Command Reference
terraform -chdir=infra/terraform apply -var environment=staging
terraform -chdir=infra/terraform apply -var environment=prod
python scripts/smoke_test.py --env prod --junit output/smoke.xml
python scripts/validate_import.py --env staging --strict
sha256sum exports/YYYYMMDD/*.json > exports/YYYYMMDD/CHECKSUMS.txt
python scripts/notify.py --channel "#epk-migration" --text "Message"
Appendix B β Contacts
Sign-Off
| Phase |
Reviewer |
Date |
Signature |
| Pre-Migration |
|
|
|
| Data Export |
|
|
|
| Schema Transform |
|
|
|
| Import Validation |
|
|
|
| DNS Cutover |
|
|
|
| Smoke Tests |
|
|
|
| Post-Migration |
|
|
|
Generated from Base44 audit (t_014f13b3) and Terraform infra (t_a8af80b0). Review with team before execution.