Vercel & Netlify
Push to Git, get a global site with preview URLs, serverless functions and edge caching.
In 30 seconds
Vercel and Netlify are frontend cloud platforms. You connect a Git repository, and every push builds your site and deploys it to a global CDN; every pull request gets its own preview URL. They also run serverless functions and edge code, so a Next.js, Astro, Nuxt or SvelteKit app can have its server parts without you managing a server. You trade some control and cost predictability for an extremely fast workflow.
Not in my daily stack — I know the concepts and would learn the details when a project needs it.
Why it matters
- They remove almost all deployment work for frontend apps: no Nginx, no certificates, no CI scripts for the basic case.
- Preview deployments for every pull request change how teams review: designers and clients click a real link instead of reading a description.
- Vercel builds Next.js, so ISR, streaming, image optimisation and middleware work with zero configuration there; Netlify supports Next.js through its OpenNext-based adapter.
- Teams pick them to ship marketing sites, docs and frontends quickly, often with the heavy backend and database hosted elsewhere.
How it works
01What they actually do
Think of these platforms as a build server, a CDN and a serverless runtime glued together by Git. When you push, the platform clones the repo, detects the framework, runs the build command, and splits the output. Static files (HTML, CSS, JS, images) go to a global CDN with long caching. Server code (API routes, server-rendered pages, server actions) is packaged into functions that run on demand in one or more regions. Middleware or edge functions run before the cache on a lightweight runtime close to the user. Every deployment is immutable and has its own URL; "production" is just an alias that points at one of them. That is why rollback is instant: you move the alias back to an older deployment, nothing is rebuilt. Compared with a VPS, you no longer think about servers, but you do think about function duration, regions, caching headers and the bill.
- Static assets → CDN. Server code → functions. Middleware → edge.
- Every deploy is immutable; production is an alias.
- Preview deployments per branch or pull request.
02Setting up a project step by step
Create an account, import the repository from GitHub, GitLab or Bitbucket, and accept the detected framework settings. The first deploy usually works without changes. Then do the real setup. Add environment variables per environment (Production, Preview, Development) in the dashboard, and never let preview builds use production secrets or the production database. Add your custom domain: point an apex domain with an A record or ALIAS, and a www subdomain with a CNAME, as the platform instructs; certificates are issued automatically. Protect previews with the platform's deployment protection if they show unreleased work. Set the function region to the same region as your database. Finally, connect the CLI for local work: it pulls environment variables and can reproduce the platform's build locally.
# Vercel
npm i -g vercel
vercel link # connect this folder to a project
vercel env pull .env.local
vercel # preview deploy
vercel --prod # production deploy
# Netlify
npm i -g netlify-cli
netlify link
netlify dev # local server with functions and redirects
netlify deploy --prod
03Rendering and caching: static, ISR, SSR, edge
Where your page is rendered decides speed and cost. Static pages are built once and served from the CDN: fastest and nearly free. Incremental Static Regeneration (ISR) serves a cached page and regenerates it in the background after a revalidate period, or on demand when your CMS calls a revalidation endpoint, so you get static speed with fresh content. Server-side rendering runs a function on every request: needed for personalised pages, but each request costs function time. Middleware runs before the cache on every matching request, so keep it tiny: redirects, rewrites, auth cookie checks, A/B bucketing. Both platforms honour standard Cache-Control headers, and Vercel also reads CDN-Cache-Control and Vercel-CDN-Cache-Control for CDN-only rules. Netlify uses Netlify-CDN-Cache-Control and supports cache tags for targeted purges. A good rule: render static by default, ISR for content, SSR only where the response truly depends on the request.
// app/blog/[slug]/page.tsx (Next.js App Router)
export const revalidate = 3600; // regenerate at most once per hour
export async function generateStaticParams() {
const posts = await fetch("https://cms.example.com/posts").then((r) => r.json());
return posts.map((p: { slug: string }) => ({ slug: p.slug }));
}
export default async function Post({ params }: { params: Promise<{ slug: string }> }) {
const { slug } = await params;
const post = await fetch("https://cms.example.com/posts/" + slug, {
next: { tags: ["post-" + slug] },
}).then((r) => r.json());
return <article><h1>{post.title}</h1></article>;
}
04Functions: limits and how billing works
Both platforms run your server code as functions, mostly on Node.js. On Vercel, functions use Fluid compute by default: one instance can serve many concurrent requests, which reduces cold starts and cost for I/O-heavy work such as calling a database or an AI API. Billing is by active CPU time, provisioned memory and invocations, so time spent waiting on network costs much less than raw duration. Edge Functions and middleware run on a lighter V8 runtime; Vercel now recommends the Node.js runtime for most functions. Netlify Functions run on AWS Lambda under the hood, and Netlify Edge Functions run on Deno at the edge. Netlify uses a credit-based plan model: deploys, compute, bandwidth and requests each consume credits from a monthly allowance. Both have maximum durations, request body size limits and memory limits per plan, so long jobs belong in a queue or a background worker elsewhere.
05Plans and pricing traps
Vercel's Hobby plan is free but for personal, non-commercial use only; client and company projects need Pro, which is priced per seat with a monthly usage credit, then pay-as-you-go. New Pro teams get a default spend budget with alerts and an option to pause projects at the limit: keep that on. Netlify has Free, Personal and Pro plans with a monthly credit allowance; when credits run out, sites can be paused unless you buy more or enable auto recharge. The traps are similar on both: a viral page that is server-rendered on every request, large unoptimised images or video served as bandwidth, bots hitting dynamic routes, image optimisation on thousands of source images, and preview builds triggered by every commit in a busy monorepo. Check prices on the official pricing pages before a client decision; both companies change their models regularly.
- Hobby on Vercel is non-commercial: client work needs Pro.
- Turn on spend limits or budget alerts on day one.
- Cache aggressively; uncached SSR is where bills grow.
Use it when
- Frontend apps and marketing sites built with Next.js, Astro, Nuxt, SvelteKit or Remix that benefit from a CDN and previews.
- Teams that want preview URLs for every pull request for design, QA and client review.
- Projects without a dedicated DevOps person, where the time saved on deployment is worth more than the platform margin.
- Jamstack sites with a headless CMS, where ISR or on-demand revalidation keeps content fresh.
Skip it when
- Long-running backends, WebSockets servers, queue workers or cron-heavy jobs: use a VPS, containers or a dedicated backend platform.
- High-bandwidth media sites where per-GB pricing makes a VPS or object storage plus a CDN much cheaper.
- Strict data residency or networking needs (private networks, fixed egress IPs) that require enterprise plans.
Alternatives
- Cloudflare Pages / Workers
Generous free tier and very cheap bandwidth; Next.js runs through the OpenNext adapter on Workers.
- VPS + Docker + Nginx
Fixed price and full control; you handle builds, TLS, caching and rollbacks yourself.
- AWS Amplify / Cloud Run
Stay inside a cloud you already use, with more control and more setup work.
- Self-hosted Next.js (standalone)
next build with output standalone runs anywhere Node runs, including Docker on a VPS.
Best practices
- Separate environment variables for Production, Preview and Development; previews must not touch production data.
- Put functions in the same region as the database to avoid cross-region latency on every query.
- Default to static and ISR; use SSR only where content depends on the request.
- Set spend limits and usage alerts, and review the usage dashboard monthly.
- Protect preview deployments that show unreleased work, and block search engines from indexing them.
- Keep middleware small and scoped with a matcher so it does not run on static assets.
- Use the platform's instant rollback and keep database migrations backward compatible so rollback is safe.
Common mistakes
- Using Vercel Hobby for a client's commercial site.
- Pointing preview builds at the production database, then running destructive migrations from a branch.
- Running heavy work (PDF generation, video processing, long AI calls) in request functions until they hit timeouts.
- Putting secrets in NEXT_PUBLIC_ variables, which ship to the browser.
- Leaving bots and crawlers free to hit uncached dynamic routes, multiplying function costs.
Deep dive
06How the request path works: routing, cache and functions
A request reaches the nearest edge location. First, platform routing rules run: redirects, rewrites and headers from your framework or config files. Then middleware runs if it matches. Next the CDN cache is checked using the URL and any cache keys or Vary headers. A cache hit returns immediately and costs only a CDN request and bandwidth. A miss invokes the function in its configured region, which may be far from the edge, so every miss pays the edge-to-region trip plus your database round trips. Stale-while-revalidate lets the CDN serve stale content while refreshing in the background. Cookies are the hidden enemy of caching: a response that depends on a session cookie must not be shared, so split pages into a cached shell and small personalised parts loaded on the client or streamed.
// next.config.ts: long cache for a public API route, revalidated in the background
import type { NextConfig } from "next";
const config: NextConfig = {
async headers() {
return [
{
source: "/api/public/:path*",
headers: [{ key: "Cache-Control", value: "public, s-maxage=300, stale-while-revalidate=86400" }],
},
];
},
};
export default config;
07Connections to databases from serverless functions
Functions scale out by creating more instances, and each instance that opens its own TCP connections to Postgres can exhaust the database's connection limit under load. Three tools solve this. First, put a pooler in front of the database: PgBouncer, the pooled endpoint of a managed provider, or Prisma Accelerate, and use transaction mode. Second, prefer drivers designed for serverless, such as HTTP or WebSocket drivers from serverless Postgres providers, for edge and short-lived functions. Third, with Vercel Fluid compute an instance serves many requests, so a small module-level pool is reused efficiently; use the waitUntil or attachDatabasePool helpers so idle connections are closed before the instance is suspended. Always put the function region next to the database: one region hop per query, multiplied by ten queries per page, is the difference between 50 and 500 milliseconds.
08Security: secrets, previews and the edge
Environment variables are encrypted at rest, but anything prefixed for the client (NEXT_PUBLIC_, PUBLIC_, VITE_) is inlined into the browser bundle: treat those as public. Scope sensitive variables to Production only, and mark them sensitive so they cannot be read back from the dashboard. Previews are a real attack surface: a pull request from a fork could run code at build time with your secrets, which is why the platforms do not expose secrets to fork builds by default; keep it that way. Use deployment protection (password, SSO or Vercel Authentication) for previews of unreleased work, and add an X-Robots-Tag noindex header so they are never indexed. Turn on the firewall and bot protection features for login and API routes, and add rate limiting for expensive endpoints, since every abusive request is billed function time.
Real-world scenarios
A marketing site goes viral and the bill spikes
Problem
A server-rendered landing page received a burst of traffic from social media. Function usage and the bill grew far beyond the plan's included credit in two days.
How to solve it
First enable or lower the spend limit so the risk is capped. Look at the usage dashboard to confirm which routes consumed function time. Then make the landing page static or ISR: move personalisation (greeting, cart count) to client components or a small API call, and set revalidate so the page is rebuilt every few minutes at most. Add s-maxage and stale-while-revalidate headers to public API routes. Check images: use the image component with sensible sizes, or pre-optimised assets on object storage. Enable bot protection if crawlers made up much of the traffic. The same traffic should then cost mostly CDN requests and bandwidth.
Next.js app on Vercel with a database in another region
Problem
Pages that list products take 1–2 seconds on Vercel, while the same app on a laptop near the database responds in 200 ms.
How to solve it
The function runs in the platform's default region, far from the database, and each page makes several sequential queries, each paying a cross-region round trip. Set the project's function region to the database's region in project settings (or move the database). Then reduce round trips: run independent queries in parallel with Promise.all, combine queries, and add indexes. Cache stable data with fetch caching or unstable cache helpers and tags, and make product lists ISR with on-demand revalidation when products change. Measure again with the platform's observability or server timing headers to confirm the time now goes to the queries themselves.
Moving a client off a platform to a VPS
Problem
A stable, high-traffic site with predictable load costs much more on a frontend platform than the client wants to pay, and previews are no longer used much.
How to solve it
Build Next.js with output: 'standalone', create a slim Docker image, and run it behind Nginx or Caddy on a VPS, with a CDN such as Cloudflare in front for static assets and caching. Replace platform features one by one: ISR works on a single Node server with the file cache, or use a shared cache handler with Redis if you run several instances; image optimisation needs sharp installed; cron jobs move to a scheduler or systemd timers; redirects move to the framework config or Nginx. Keep GitHub Actions for build and deploy with tagged images for rollback. Run both in parallel, then switch DNS with a low TTL.
Cheat sheet
- Deploy a preview (Vercel)
vercel- Deploy to production (Vercel)
vercel --prod- Pull env vars locally (Vercel)
vercel env pull .env.local- Roll back production (Vercel)
vercel rollback <deployment-url>- Run locally with functions (Netlify)
netlify dev- Deploy to production (Netlify)
netlify deploy --prod- Cache a public response at the CDN
Cache-Control: public, s-maxage=300, stale-while-revalidate=86400- Revalidate a tag on demand (Next.js)
revalidateTag("post-hello-world")- Scope middleware away from assets
export const config = { matcher: ["/((?!_next/static|_next/image|favicon.ico).*)"] }
Questions & answers
Q1What is a preview deployment and why is it valuable?
A preview deployment is a full, isolated build of a branch or pull request with its own URL, created automatically on push. It runs the same build as production but with preview environment variables. Its value is in review: designers, product owners and clients see the real change on a real link, QA can test it, and automated checks such as Lighthouse or end-to-end tests can run against it before merging. Because each deploy is immutable, the preview you approved is exactly what gets promoted. The main caution is data: previews should use a staging database or seeded data, and be protected if they show unreleased features.
Q2How does ISR work on these platforms?
Incremental Static Regeneration means a page is generated statically and cached on the CDN, then regenerated later without a full rebuild. With time-based revalidation, the first request after the revalidate window still gets the cached page, while the platform regenerates it in the background; the next visitors get the fresh version. With on-demand revalidation, your CMS or backend calls an endpoint that runs revalidatePath or revalidateTag, and the platform purges and rebuilds just those pages. You get static performance and cost with content that updates in seconds. On Vercel this is native; on Netlify it works through its Next.js runtime with durable caching.
Q3Vercel or Netlify: how would you choose?
For Next.js, Vercel is usually the smoothest because it builds the framework and supports new features on release day. Netlify supports Next.js well through its adapter and is strong for multi-framework teams, Astro sites, forms, and built-in features like split testing and identity. Compare the plan model for the expected traffic: Vercel prices Pro per seat with usage-based compute, Netlify uses a credit allowance per plan. Also check region choices, function limits, team features such as SSO, and where the backend lives. For a client, I would build a small spike on both only if the decision is unclear; usually the framework decides it.
Q4Can you host a full backend on Vercel or Netlify?
You can host API routes and server actions that do short request and response work: reading and writing a database, calling third-party APIs, handling webhooks. What does not fit well is long-running or stateful work: WebSocket servers, queue consumers, heavy batch jobs, or anything that must run longer than the function limit. The usual architecture is the frontend and a thin backend-for-frontend on the platform, with a managed database (Postgres from Neon, Supabase or a cloud provider), and a separate worker service for queues and scheduled jobs on a VPS or containers. That keeps the fast workflow while putting heavy work where it is cheaper.
Q5How do you roll back a bad deploy?
Every deployment is immutable and stays available, and production is an alias pointing at one of them. On Vercel you use Instant Rollback in the dashboard or vercel rollback with the deployment URL; on Netlify you pick an older deploy and publish it, optionally locking auto-publishing while you fix the issue. No rebuild happens, so it takes seconds. The catch is anything outside the deploy: database migrations, changed environment variables and external webhooks are not rolled back. That is why migrations should be backward compatible (expand first, contract later), so the previous version still works with the new schema.
Senior-level questions
S1When does a frontend platform stop being cost-effective, and how do you decide to leave?
Model the cost per unit of traffic. Platforms are cheap when most traffic is cached and the team is small: the money saved on DevOps time outweighs usage pricing. They get expensive with high bandwidth (media, large downloads), lots of uncached server rendering, heavy image optimisation, many seats, or long-running compute. Before leaving, optimise: static and ISR by default, caching headers, image budgets, bot protection, right region. If the bill is still high, compare total cost of ownership: VPS or containers plus a CDN, plus engineering time for CI, previews, TLS, monitoring and on-call. A hybrid often wins: keep the frontend and previews on the platform, move heavy APIs, workers and media to cheaper infrastructure.
S2Edge runtime or Node.js runtime for server code?
The edge runtime starts fast and runs close to the user, but it has a restricted API (no full Node.js, limited packages, smaller code size, limited CPU time). It shines for logic that needs no database or only a globally replicated store: redirects, geolocation, A/B bucketing, auth token checks, header rewriting. Most real work talks to a database in one region, and running that at the edge means every query crosses the world, so it gets slower, not faster. Node.js functions in the database region, especially with Fluid compute concurrency, are usually the better default and Vercel now recommends them. Use edge middleware for thin routing decisions and keep data access regional.
S3How do you design preview environments that include a database?
Static previews are easy; data is the hard part. Options from simple to rich: share one staging database for all previews (cheap, but branches with migrations collide); use database branching from providers such as Neon, where each preview gets a copy-on-write branch created by a webhook or CI step and deleted when the pull request closes; or seed an ephemeral database per preview from fixtures. Migrations run against the branch during the build or a separate CI job. Secrets per preview come from the integration, never from production. Add cleanup automation, or branches and their costs accumulate. The trade-off is setup complexity versus confidence: branching gives realistic tests of migrations before they reach production.
Glossary
- Preview deployment
- An automatic, isolated deployment of a branch or pull request with its own URL.
- ISR
- Incremental Static Regeneration: serve a cached static page and regenerate it after a time window or on demand.
- Edge function
- Lightweight code that runs in many locations close to users, before the cache, with a restricted runtime.
- Fluid compute
- Vercel's function model where one instance handles many concurrent requests and billing follows active CPU time.
- Instant rollback
- Pointing the production alias back to an earlier immutable deployment without rebuilding.
- s-maxage
- A Cache-Control directive that sets how long shared caches such as CDNs may keep a response.
- Build minutes
- Time spent building deployments; limited or billed per plan, and multiplied by busy monorepos.
- OpenNext
- An open-source adapter that lets Next.js apps run on platforms other than Vercel, such as Netlify, AWS or Cloudflare.
Keep learning
Have a product in mind?Let's build it.
Tell me about your idea, your product or your team. I usually reply within one working day.