Skip to main content
ASoc
Comparison

Vercel vs. AWS Amplify: The Bundled Backend Is the Real Question

13 runtime dependencies, zero AWS SDK packages, and a build that splits 392 static pages from 8 dynamic routes with no deployment config authored for either.

The ASoc Team7 min read

Vercel deploys a Next.js app and gets out of the way — the framework's own static/dynamic split becomes the deployment topology, with zero YAML. AWS Amplify deploys the same app onto AWS's broader stack, and offers to also be your auth provider, GraphQL API and database. Choose Vercel when the backend is already decided; choose Amplify when you want AWS's services bundled with the hosting. This storefront picked the first shape, on purpose, and ships zero AWS SDK packages as a result.

The comparison at a glance

VercelAWS Amplify
What it deploysNext.js, framework-aware (SSG/ISR/SSR/Edge inferred per route)Any front end, plus optional backend resources it provisions
Bundled backendNone — bring your ownCognito (auth), AppSync (GraphQL), DynamoDB, S3
Config surfacenext.config.ts, mostly optionalamplify.yml build spec + backend resource definitions
Image optimizationBuilt-in on-demand resizing (a paid dimension, if used)Not part of the platform — you wire your own
This repo's usageHosting + @vercel/analytics onlyNot used at all — zero @aws-sdk/* packages
Where the backend actually livesSupabase (Postgres, RLS, Auth, Storage)Would be Amplify's own Cognito/AppSync/DynamoDB stack

The decision this repo actually made

package.json has 13 runtime dependencies. None of them starts with @aws-sdk/, and none is aws-amplify:

"dependencies": {
  "@mdx-js/loader": "^3.1.1",
  "@mdx-js/react": "^3.1.1",
  "@next/mdx": "^16.3.0",
  "@supabase/ssr": "^0.12.0",
  "@supabase/supabase-js": "^2.110.0",
  "@vercel/analytics": "^2.0.1",
  "lucide-react": "^1.21.0",
  "next": "16.2.9",
  "react": "19.2.4",
  "react-dom": "19.2.4",
  "rehype-slug": "^6.0.0",
  "remark-gfm": "^4.0.1",
  "server-only": "^0.0.1"
}

Two of those, @supabase/ssr and @supabase/supabase-js, are the entire backend: Postgres with row-level security, auth, and file storage for the gated downloads. That's the actual comparison Amplify invites — not "where does the HTML get served," which both platforms answer well, but "who provides auth, the database, and the API." Amplify's answer is Cognito + AppSync + DynamoDB, provisioned and configured through the platform itself. This repo's answer is a separate managed Postgres project reached over https, with RLS enforcing access at the row level rather than through IAM policies — the reasoning for that specific choice, and the real policy count behind it, is Supabase vs Firebase. Vercel has no opinion on that decision either way; it hosts whatever the app calls out to — though it will happily provision a Postgres for you through its own marketplace, which is the narrower comparison in Vercel Postgres vs. Supabase.

Where Vercel's framework-awareness actually shows up

The distinction isn't marketing — it's visible in what a build does with each route. A next build of this repository today compiles 392 pages to static HTML at build time and leaves exactly 8 routes dynamic, server-rendered per request:

ƒ /api/download
ƒ /api/webhooks/lemonsqueezy
ƒ /auth/callback
ƒ /dashboard
ƒ /dashboard/settings
ƒ /login
ƒ /reset-password
ƒ /signup

ƒ Proxy (Middleware)

Vercel reads that build output and deploys accordingly — the 392 static pages go straight to the CDN edge, and the 8 dynamic routes plus the proxy become functions, with no deployment config authored for any of it. Amplify's Next.js support works from the same build output, but arriving there means the platform's own build pipeline (amplify.yml) has to be told how to run next build and what to do with the result; it isn't the platform Next.js's own team ships the framework alongside. Neither gap is disqualifying — it's the cost of Amplify's real advantage, which is provisioning AWS resources (a Cognito pool, a DynamoDB table) from the same place that hosts the front end.

What Vercel charges for that this app doesn't use

next.config.ts has no images block. That's not an oversight — this catalog serves 111 products' screenshots as plain <img> tags pointed at pre-built WebP variants (cardImage() / viewImage() in src/lib/imageVariants.ts), generated once at build time by scripts/images/build-variants.ts rather than resized per-request by Vercel's image optimizer. Vercel's optimizer is billed per source image transformed; a catalog this size run through it live would be a real, recurring cost line. Amplify doesn't have an equivalent built-in image pipeline to compare against — it's simply not a dimension either platform charges this app for, because the app opted out of the one that would have.

The session layer is the other place Vercel-specific behavior matters. src/proxy.ts runs on every request to refresh the Supabase session and rewrite auth cookies before a Server Component renders:

// src/proxy.ts
export async function proxy(request: NextRequest) {
  let response = NextResponse.next({ request });
  const supabase = createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    { cookies: { /* read + rewrite request/response cookies */ } },
  );
  // …getClaims(), never getSession() — see auth-react
}

This is Next.js middleware, not a Vercel-specific API — it would run the same way on Amplify's Next.js compute, or anywhere else that executes the framework's own server runtime. The point isn't portability; it's that neither platform's marketing page is where this behavior lives. It's in the framework, and both platforms are graded on how transparently they run it.

Security headers are the framework's job either way

The same "who owns this config" question applies to response headers. This repo's CSP, HSTS and frame-blocking rules are declared once, in the framework's own headers() hook:

// next.config.ts
const nextConfig: NextConfig = {
  async headers() {
    return [{ source: "/(.*)", headers: securityHeaders }];
  },
};

That single function is what emits Content-Security-Policy, Strict-Transport-Security, X-Frame-Options and X-Content-Type-Options on every response. Vercel reads it directly out of the Next.js build and applies it — no separate configuration surface. On Amplify, the equivalent typically means either the same next.config.ts hook (if running Amplify's SSR compute, which does execute the framework's own server) or a CloudFront response-headers policy layered on top if serving through Amplify's static hosting path instead. Neither is hard, but it's one more place the two platforms diverge on how much of AWS's broader toolkit a Next.js-specific concern ends up routed through.

Troubleshooting

SymptomCauseFix
A route that should be static shows up dynamic in next build outputSomething in it reads request-time data — cookies, headers, searchParams in a Server ComponentCheck for cookies()/headers() calls or an un-awaited dynamic API; see Next.js static rendering
Deploying to Amplify and the build can't find next.config.ts outputAmplify's Next.js support needs its own build-spec awareness of the framework versionConfirm the amplify.yml uses Amplify's Next.js 13+ SSR support, not the legacy static-export path
Vercel image-optimization costs spike unexpectedlyEvery unique next/image src+size combination is billed as a separate source transformationPre-build fixed-size variants at deploy time (this repo's approach) if the image set is finite and known ahead of request time
getSession() returns a session that later 401s on Amplify's own authAmplify's Cognito tokens have a different validation path than an unrelated provider'sIrrelevant here since this app never adopted Cognito — but the general lesson holds on any platform: validate the token server-side, never trust a client-supplied session object
A team assumes Amplify is "free" for the backend once already using it for hostingCognito/AppSync/DynamoDB are separately metered AWS services, not bundled computePrice the backend services independently of the hosting decision — the two are billed on unrelated axes

Frequently asked questions

Is AWS Amplify cheaper than Vercel? It depends what's being compared. Amplify's hosting tier and Vercel's are broadly similar for a static/SSR front end. The cost difference shows up if the backend also runs on Amplify's bundled services (Cognito, AppSync, DynamoDB), which are billed as separate AWS resources either way — so the honest comparison is Vercel-plus-your-backend-of-choice against Amplify-plus-its-bundled-backend, not the hosting tiers alone.

Does Vercel lock you into Vercel-specific APIs? Very little of this repository does. The proxy is standard Next.js middleware, the analytics package is optional and swappable, and the rest of the app — including the entire backend — is Supabase, reachable from any host. The image optimizer is the one genuinely Vercel-specific service this app deliberately opted out of.

Can you run a Supabase backend on AWS Amplify hosting? Yes — nothing about Amplify's hosting requires using its bundled backend services. This repo's actual comparison isn't really "Vercel vs. Amplify" as hosting platforms; it's "a specialized Next.js host plus a chosen backend" vs. "a general AWS host with its own backend bundled in," and the bundling is Amplify's real differentiator, not the hosting itself.

Why does this matter for choosing a template's hosting? Because the backend decision usually costs more engineering time than the hosting decision. A landing page template with no backend runs identically well on either platform. The moment auth, a database, or file storage enters the picture, the real question is which backend model — RLS on Postgres, or IAM-scoped Cognito/DynamoDB — fits the data, not which platform's dashboard looks better.

Templates in this post

ASoc Surge, an AI startup landing page, and ASoc Synth, an AI workspace SaaS landing page, both ship as pure static builds — the case where the Vercel-vs-Amplify hosting question genuinely doesn't touch a backend decision at all. ASoc Tempo, a time-tracking SaaS landing page, is the closer case: a marketing shell for a product that needs auth and a database once it's wired up, which is exactly where the backend question this post covers stops being hypothetical.

Browse the full sets: Next.js landing page templates and Tailwind landing page templates.

Keep reading

Comparison9 min read

Vercel vs Cloudflare Pages: Count the Routes That Need a Runtime

414 prerendered pages any CDN serves the same way, 8 dynamic routes, and exactly 2 that pin the Node runtime for node:crypto. Those two lines are the whole decision.

Read more
Comparison8 min read

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.

Read more