Vercel vs. DigitalOcean: What Owning the Server Actually Costs
Two Route Handlers, zero Dockerfiles, zero nginx configs — what this storefront's own deploy setup says about Vercel vs a DigitalOcean Droplet.
Vercel builds and runs your app for you — push to a branch and it's deployed, scaled, and torn back down between requests. DigitalOcean gives you compute: either a Droplet (a raw Linux VM you administer yourself) or App Platform (a managed layer on top of the same Droplets). The real decision isn't price or brand — it's whether you want to own the server, and this codebase's own deploy setup answers that question by what it doesn't contain.
What "owning the server" actually requires, checked against this repo
A Droplet is a VM with nothing on it. Getting a Next.js app running on one means adding, at minimum: a process manager to keep next start alive across crashes and reboots (pm2 or a systemd unit), a reverse proxy for TLS termination and to put port 443 in front of Node's port (nginx or Caddy), and a deploy script or CI job to pull, install, build and restart on every push. None of that exists in this repository:
$ find . -maxdepth 2 -iname "Dockerfile*" -o -iname "*.nginx*"
# (no output)
$ grep -n "output:" next.config.ts
# (no output — no `output: "standalone"` either)
$ grep -rn "pm2\|systemd" package.json
# (no output)
Zero results across all three checks. That's not an oversight — it's what a codebase looks like when it was built assuming a platform that removes those layers entirely. Deploying this exact repo to a Droplet wouldn't mean flipping a config flag; it would mean writing a Dockerfile, a systemd unit, and an nginx config from scratch, none of which currently exist anywhere in the tree.
What actually deploys on Vercel today
Production has exactly two Route Handlers, both explicit about their runtime:
// src/app/api/webhooks/lemonsqueezy/route.ts
export const runtime = "nodejs";
// src/app/api/download/route.ts
export const runtime = "nodejs";
Neither sets maxDuration — the platform default is enough for both (verify a webhook signature and write to Postgres; check an entitlement and mint a short-lived signed URL). Everything else in the app — all 480 static pages in the current build — is pre-rendered at build time and served from Vercel's CDN with no server process running per request at all. There is no "app" listening on a port here in the sense a Droplet would run one; there's a build output Vercel's platform knows how to serve, plus two short-lived functions.
That build is fast enough to make the "pre-render everything" strategy practical at this scale:
Generating static pages using 3 workers (0/480) ...
Generating static pages using 3 workers (120/480)
Generating static pages using 3 workers (240/480)
Generating static pages using 3 workers (360/480)
✓ Generating static pages using 3 workers (480/480) in 6.8s
480 pages in 6.8 seconds, measured on this exact build. On Vercel that number only matters for how quickly a deploy goes live; on a Droplet, it's the number you'd have to fit into a deploy script you write yourself — clone, install, build, then restart the process manager without dropping in-flight requests — because there's no platform watching the git remote and doing that for you.
Where App Platform actually narrows the gap
DigitalOcean's App Platform is the fairer comparison, not a bare Droplet — it takes a git repo, runs a build, and deploys it without you managing the VM directly, closer to Vercel's model. The real remaining differences are in what's automatic versus configured:
| Vercel | DigitalOcean App Platform | DigitalOcean Droplet | |
|---|---|---|---|
| Who patches the OS | Vercel | DigitalOcean | You |
| TLS certificate | Automatic, zero-config | Automatic | You configure (Let's Encrypt via Certbot, or a proxy) |
| Static asset CDN | Built in | Built in (CDN add-on) | You add one, or serve directly |
| Scale-to-zero on idle | Yes, per-function | No — apps run continuously | No — the Droplet runs continuously |
| Preview deployments per branch/PR | Built in | Not built in | Not built in |
| Framework-aware build (Next.js) | Native, first-party | Buildpack-based, generic | You script it |
The Droplet column is where this codebase's missing Dockerfile/nginx/systemd actually bites — App Platform and Vercel both remove that layer, just with different degrees of Next.js-specific awareness underneath.
The one config that ports cleanly to any of the three
Not everything in this repo is Vercel-specific. Its CSP and security-response headers are defined once, as a plain Next.js config export:
// next.config.ts
async headers() {
return [{ source: "/(.*)", headers: securityHeaders }];
},
headers() is core Next.js, not a Vercel feature — it runs identically whether next start is executed by Vercel's platform, App Platform's buildpack, or a pm2-managed process on a bare Droplet, because it's the framework's own server emitting the headers, not something injected at the CDN edge. That's the actual boundary worth knowing: build-and-deploy automation (patching, TLS, scale-to-zero, preview URLs) is genuinely platform-specific and is what this whole comparison is about; application-level configuration that Next.js owns travels with the code regardless of where it runs.
Why this matters more than the pricing page
DigitalOcean's per-resource pricing (a fixed monthly Droplet cost, or App Platform's per-container pricing) can be cheaper than Vercel's per-invocation model at steady, predictable traffic — that's a real tradeoff. But it's the wrong axis to decide on first for a codebase like this one: this repo has no infrastructure code to run anywhere except through a platform that builds and serves it automatically. The cost of adopting DigitalOcean's Droplet tier isn't the monthly bill, it's writing the Dockerfile, the reverse-proxy config, and the deploy pipeline this repo has never needed — work that has to happen once, up front, before the pricing comparison even applies.
Troubleshooting: matching the platform to what you're actually running
| Symptom | Cause | Fix |
|---|---|---|
| "It works locally but nothing deploys" on a Droplet | No process manager — next start exits when the SSH session closes | Add pm2 start npm --name app -- start (or a systemd unit) before anything else |
| Site loads over HTTP but not HTTPS on a Droplet | No reverse proxy terminating TLS | Put nginx or Caddy in front of the Node process, or use a load balancer that terminates TLS for you |
| A Route Handler works locally but times out on a serverless platform | Doing long-running work in a function meant for short requests (this repo's two routes deliberately never do this) | Move long-running work to a background worker or a job queue — not a route handler |
| App Platform build fails on a Next.js-specific feature | Its buildpack is generic Node, not Next.js-aware the way Vercel's build pipeline is | Check App Platform's Next.js buildpack docs for the specific feature, or add a custom build command |
Frequently asked questions
Does this app's database live on Vercel?
No — neither Vercel nor a Droplet hosts this app's data. Postgres runs on Supabase, reached from process.env.NEXT_PUBLIC_SUPABASE_URL, entirely independent of whichever platform runs the Next.js build. Moving this app's compute from Vercel to DigitalOcean wouldn't touch the database layer at all; DigitalOcean's own Managed Databases product would only become relevant if you were also moving the Postgres instance, which is a separate decision from where the app itself runs.
Is a Droplet cheaper than Vercel? Often, at predictable steady traffic — a fixed monthly VM cost versus Vercel's per-invocation pricing. But the comparison only makes sense once you've built (or bought) the process-manager, reverse-proxy and deploy-pipeline layer a Droplet doesn't include. This repo has none of that today.
Does DigitalOcean have anything like Vercel's per-branch preview deployments? Not built in on either App Platform or a Droplet. You'd wire your own CI to spin up a preview environment per PR, which Vercel does automatically for every push.
Is App Platform basically the same as Vercel? Closer than a Droplet, but its build step is a generic Node buildpack rather than a Next.js-native build pipeline — App Router features that Vercel's build understands out of the box may need a custom build command on App Platform.
Why does this post keep pointing at the same two Route Handlers? Because they're the entire dynamic surface of this codebase — the fact that decides whether a hosting platform's request-scoped compute model fits is how much of your app actually needs it, and here the honest answer is "two small functions, nothing else."
Templates in this post
ASoc Magnet (a lead-generation SaaS landing page), ASoc Mind (an AI creative-services marketing site) and ASoc Momentum (an AI strategy-agency site) all deploy the same way — static build, two Route Handlers, no server to administer.
Browse the full sets: Next.js landing page templates, Tailwind landing page templates. For the same route-census approach against other platforms, see Vercel vs. Render, Vercel vs. AWS Amplify and Vercel vs. Cloudflare Pages.
