跳到正文
DEV Community· Rodrigo Orzari·· 2 小時前AI 評分57

我如何在零停機下將生產平台由 DigitalOcean 遷移至 AWS

How I Migrated a Production Platform from DigitalOcean to AWS With Zero Downtime

AI 導讀

Rodrigo Orzari 將 Compare Cloud Costs 生產平台由 DigitalOcean 遷移至 AWS,透過雙寫及分階段 DNS 切流實現零停機。遷移後,複雜多表查詢延遲由 120ms 降至約 28ms,基礎設施月度支出維持約 ~$100/mo,並由固定方案轉為按需付費。遷移時以 27,834 筆定價資料進行逐行核對及加密校驗,切換前後所有數值一致。

正文

How I Migrated a Production Platform from DigitalOcean to AWS With Zero Downtime

I built Compare Cloud Costs — a free tool that benchmarks the same workload across 24 cloud providers. This is the story of moving my own platform off DigitalOcean onto AWS, written for engineers planning a similar move. (First published on the CCC blog; adapted for DEV.)

TL;DR

  • Why: scaled past 27,000 live pricing records + multi-cloud AI diagram parsing; hit DigitalOcean's static scaling walls on App Platform and Managed PostgreSQL.
  • Target stack: AWS Amplify (Next.js 15 SSR) + CloudFront, Aurora Serverless v2 (0.5–16 ACU), ECS on Fargate, Bedrock (Nova multimodal), Route 53.
  • Zero-downtime strategy: dual-write ingestion pipelines, DNS TTL lowered to 60s, staged Route 53 weighted shifts, row-by-row checksum validation across 27,834 pricing rows.
  • Outcome: query latency dropped from 120ms to ~28ms average (3x+ faster); baseline infra run-rate stayed around ~$100/mo but shifted from fixed tiers to elastic pay-per-use.

The irony of building a cloud cost platform

We spend every day normalizing and benchmarking millions of price points across 24 cloud providers — helping engineers escape lock-in and surprise bills — while running on infrastructure of our own.

For the early days, DigitalOcean was the right call: clean UI, simple droplets, App Platform that let a solo founder ship prototypes fast. But once the SKU database passed 27,000 live pricing records and the architecture-diagram parser started chewing through complex enterprise multi-cloud topologies, the cracks showed: rigid fixed tiers, static scaling walls, zero partnership flexibility.

When the provider can't grow with you into high-compute workloads and serious data density, the conclusion is obvious: you outgrow the tier. It was time to practice what we preach. Today Compare Cloud Costs runs 100% natively on AWS.

Before vs. after

Layer DigitalOcean (before) AWS (after)
Frontend App Platform (basic compute pools) Amplify Hosting, Next.js 15 SSR + CloudFront edge caching
Database Managed PostgreSQL (static 1 vCPU / 2 GB tier) Aurora Serverless v2, 0.5–16 ACU auto-scaling, multi-AZ
AI inference Single-region endpoints, restrictive token limits Bedrock (Nova multimodal), structured JSON output, IAM roles
Background jobs Long-lived VM ECS on Fargate — wake up, parse, terminate
DNS DO nameservers Route 53

The single biggest win: on DigitalOcean, a traffic spike meant a manual plan upgrade — paying the elevated flat rate 24/7, even at 3 AM on Sunday. With Aurora Serverless v2, the database scales in fractions of a second to absorb ingestion batches (our 24-provider daily sync) and scales back down after. Query latency on complex multi-join filters: 120ms → ~28ms.

The migration checklist (7 phases)

  1. Provision the target: AWS Organization, VPC across 3 AZs (public/private/database subnets), Aurora Serverless v2 cluster (0.5–16 ACU), security groups locked to Amplify/ECS roles.
  2. Schema + baseline export: pg_dump --schema-only --no-owner --no-privileges into Aurora; then parallel directory-format dump/restore (pg_dump -Fd -j 4 / pg_restore -Fd -j 4).
  3. Dual-run ingestion: pricing scrapers wrote to both databases simultaneously; reads stayed on DigitalOcean during testing to establish data parity.
  4. Frontend on Amplify: connect the GitHub branch, configure amplify.yml for Next.js 15 standalone output, validate preview deployments against staging Aurora.
  5. Move DNS to Route 53: lower all TTLs to 60s at least 48 hours before cutover, replicate apex/CNAME/MX/TXT records, switch registrar nameservers, verify with DNS looking glasses.
  6. Cutover: route traffic to the Amplify distribution, watch error rates/latency/cache-hit ratios in CloudWatch. Keep DigitalOcean in read-only fallback for 48h before teardown.

7 gotchas that almost broke the migration

1. PostgreSQL extension incompatibilities. DO's managed Postgres bundled pgvector/uuid extensions under pre-installed owner privileges that failed to initialize in Aurora without superuser rights. Fix: strip owner assignments (sed -i '' -e 's/OWNER TO .*;//g' ccc_schema.sql) and grant extension usage through the RDS master role before restore.

2. Aurora needs 3 AZs. Aurora Serverless v2 requires a DB subnet group spanning at least two (preferably three) AZs. Our first VPC had subnets in a single AZ — instant provisioning validation error. Fix: redesigned across us-east-1a/b/c.

3. Next.js standalone SSR in Amplify. Default Amplify configs failed to package dynamic server components — intermittent 500s on server-rendered routes. Fix: output: 'standalone' in next.config.ts, explicit cache paths in amplify.yml, Node 20.x in build settings.

4. Bedrock IAM permissions. Amplify SSR functions calling bedrock:InvokeModel were denied — the default execution role lacked the permission. Fix: inline least-privilege IAM policy scoped to the target model ARNs.

5. DNS TTLs are advisory. Despite 60s TTLs, several upstream enterprise resolvers ignored them and kept sending traffic to DigitalOcean for ~18 hours. Fix: HTTP 301 redirect at the DO App Platform ingress pointing to the canonical domain — stragglers landed on the AWS edge regardless.

6. Aurora cold-start. Min capacity 0 ACU → 3–5s latency spikes when the first daily ingestion batch woke the database. Fix: floor of 0.5 ACU keeps it warm, sub-30ms, for pennies per day idle.

7. Connection pool exhaustion. Serverless Next.js functions spawned parallel connections during spikes, threatening Postgres connection caps. Fix: RDS Proxy in front of Aurora — hundreds of concurrent invocations multiplex over a steady handle pool.

Verifying zero data loss

A cost intelligence platform can't tolerate missing records. We validated with row-count verification and cryptographic table checksums across all 27,834 pricing rows — every figure identical before and after cutover.

What I'd do differently

Set the Aurora 0.5 ACU floor from day one, and plan the 301-redirect safety net before the DNS cutover instead of discovering the TTL-ignoring resolvers mid-migration. Everything else held.


Compare Cloud Costs is a free, independent platform benchmarking the same workload across 24 cloud providers (AWS, Azure, Google Cloud, Oracle, DigitalOcean, Alibaba, Cloudflare + GPU/AI providers) — pricing refreshed weekly. There's also an MCP server so Claude/Cursor/VS Code can query normalized pricing instead of relying on stale training data. Full version of this post with architecture diagrams: comparecloudcosts.com/blog/migrating-compare-cloud-costs-from-digitalocean-to-aws

來源:DEV Community · dev.to