I moved this site off Vercel and onto AWS. Not because Vercel is bad. Vercel is excellent, and for most people it is the right answer. I moved because I wanted to own the stack, keep the bill flat and predictable, and actually understand the cloud I was standing on. This is how it is wired and what it costs.
Why move at all
Vercel and Neon are effortless. That is the whole pitch, and they deliver on it. But both are thin, well-designed wrappers over the same cloud primitives you can rent directly. You pay for the convenience, and the price climbs as you grow.
For a site I plan to keep for years, going cloud-native is the stronger long-term bet. The convenience layer is worth a lot when you are moving fast and infrastructure is not the point. It is worth less when the site is stable and you would rather own the pieces than rent the abstraction. I also just wanted to learn the primitives, because the abstractions get easier to reason about once you know what they are hiding.
What it runs on
The site is one Docker image. The Next.js app is built to standalone output and wrapped with the AWS Lambda Web Adapter, so the exact same container runs as an ordinary web server on my laptop and as a Lambda function in production. No separate serverless build, no framework-specific adapter to fight with. One image, two places to run it.
CloudFront sits in front of the Lambda. It terminates TLS, redirects HTTP to HTTPS and www to the apex, caches the fingerprinted static assets and the generated OpenGraph images, and passes everything else through to the app. An Origin Access Control signs each origin request, so the Lambda URL is reachable only through CloudFront and not directly.
Route 53 holds the DNS: the web records plus all the email authentication records (MX, SPF, DKIM, DMARC). The domain stays registered at GoDaddy; only the nameservers are delegated to Route 53.
The whole thing is defined in Terraform. GitHub Actions builds the image, pushes it to ECR with an immutable git-SHA tag, and rolls the Lambda to the new image on every merge to main. It authenticates to AWS with OIDC, so there are no long-lived access keys sitting anywhere. CloudWatch alarms, a Route 53 health check, and SNS email alerts keep watch and tell me if something breaks.
One detour worth mentioning, because it is the kind of thing that actually happens: I originally planned to use App Runner. AWS closed App Runner to new customers on April 30, 2026, and my account is newer than that, so Lambda took its place. Same container image, different compute target. The same image can also run on ECS later without a rebuild, which is exactly the point of packaging it this way.
What it actually costs
Here is the honest breakdown for a low-traffic marketing site:
- Lambda scales to zero. There is no always-on instance, and at this traffic it sits inside the free tier. Effectively nothing.
- CloudFront is pennies at this volume, much of it inside the free tier.
- Route 53 is the one real fixed cost: roughly $0.50 a month for the hosted zone, plus about $0.50 to $0.75 for the health check.
- ECR image storage is cents. The thing to watch is old images piling up over many deploys, so I prune them.
- ACM (the TLS certificate) is free.
- CloudWatch alarms and logs come to a few cents.
- SNS is negligible.
The whole bill lands under $10 a month, and most of that is the fixed Route 53 floor, not traffic. The variable, per-request cost only starts to matter at real scale, and by the time you get there you have options and a reason to spend the money.
That is the part Vercel's pricing hides from you. On a managed platform you are paying for the convenience layer whether or not your traffic justifies it. On raw AWS, a small site is genuinely small money, and the cost tracks what you actually use.
What you give up
I will be honest about the trade. Vercel's developer experience is better out of the box. You lose instant per-branch preview deployments, zero-config everything, and a lot of polish. You take on Terraform, IAM policies, a CloudFront cache you have to reason about, and a first setup that costs real hours before anything is live.
If your time is worth more than the difference, stay on Vercel. That is a completely legitimate answer, and for a fast-moving product it is usually the right one.
What you get
Control and understanding. The site is one container I can run anywhere, with nothing proprietary underneath it. The bill is small and predictable. And I now understand every piece of the path from a browser request to a rendered page, which matters more to me than the dollars saved.
If you are a solo builder or a small team that wants to own your stack, keep costs flat, and learn the cloud you are already paying for, this is worth doing. If you want to ship features and never think about infrastructure, it is not, and there is no shame in that.
For me, the math was easy. A site I want to keep for a decade should run on primitives I control, at a price that does not surprise me. This one does.
