Ik draai Next.js in productie sinds versie 9. Het grootste deel van die tijd was Vercel de voor de hand liggende keuze — deployen, vergeten, doorgaan. Maar ergens rond 2024 begonnen de facturen eruit te zien als autoleningen. Wanneer je hostingrekening voor een marketingsite je werkelijke cloud-infrastructuurkosten overschrijdt, klopt er iets niet. Dat is wanneer ik OpenNext ging onderzoeken, en na het migreren van drie productie-apps van Vercel in het afgelopen jaar, heb ik er sterke meningen over.

Dit is geen "Vercel slecht" artikel. Vercel is werkelijk uitstekend. Maar het is niet langer de enige optie, en voor veel teams is het niet de juiste. Ik neem je mee door alles wat ik heb geleerd over het zelf hosten van Next.js met OpenNext — het goede, het lelijke en het verrassend betaalbare.

Inhoudsopgave

OpenNext: Self-Host Next.js on AWS, Cloudflare, or VPS Without Vercel

Wat is OpenNext en waarom bestaat het

Next.js was ontworpen om op Vercel te draaien. Dat is geen samenzwering — het is architectuur. Functies zoals ISR (Incremental Static Regeneration), middleware, afbeeldingsoptimalisatie en server actions hebben allemaal Vercel-specifieke implementaties ingebouwd. Wanneer je probeert next start op een willekeurige server uit te voeren, krijg je een subset van wat Next.js kan doen.

OpenNext is een open-source adapter die je Next.js buildoutput neemt en deze transformeert in implementatiepakketten die op andere platforms werken. Het begon als een SST-communityproject gericht op AWS Lambda, maar vanaf v3 (de huidige hoofdversie in 2025) ondersteunt het meerdere implementatiedoelen, waaronder Cloudflare Workers, traditionele Node.js-servers en meer.

Dit is wat OpenNext eigenlijk aanpakt:

  • ISR en revalidatie — Het tag-gebaseerde revalidatiesysteem dat Vercel implementeert met hun interne infrastructuur? OpenNext recreëert dit met DynamoDB + SQS op AWS, of KV-stores op Cloudflare.
  • Afbeeldingsoptimalisatie — De Next.js <Image>-component is afhankelijk van een optimalisatie-API. OpenNext verpakt een Sharp-gebaseerde optimizer of routeert naar platformspecifieke oplossingen.
  • Middleware — Draait op de edge op Vercel. OpenNext wijst dit toe aan CloudFront Functions, Cloudflare Workers, of voert het in-process uit op VPS.
  • Server actions — Volledige ondersteuning, gerouteerd door de juiste serverfunctie.
  • Streaming en gedeeltelijke prerendering — De ondersteuning is significant verbeterd in OpenNext v3.x.

Wat OpenNext niet is

Het is geen hostingplatform. Het is geen CDN. Het is een build adapter — een vertaaglaag tussen Next.js's uitvoer en je infrastructuur. Je moet het ding nog steeds ergens daadwerkelijk uitvoeren.

Het zelf-hostinglandschap in 2025-2026

Het ecosysteem is sinds ik er eerst naar begon te kijken enorm uitgebreid. Hier is de huidige toestand:

Platform OpenNext-ondersteuning Rijpheid Het beste voor
AWS (via SST) Eerste klasse Productie-klaar Teams die al op AWS werken
Cloudflare Workers Officiële adapter Stabiel (enkele randzaken) Edge-first apps, kostenoptimalisatie
Docker/VPS Gemeenschap + officieel Stabiel Eenvoudige implementaties, bestaande infra
Kubernetes Community Helm-grafieken Rijpend Onderneming, bestaande K8s-clusters
Netlify Ingebouwd (eigen adapter) Productie-klaar Teams die zich op Netlify concentreren
Google Cloud Run Gemeenschap Experimenteel GCP-shops

De twee paden die ik persoonlijk heb getest en kan garanderen zijn AWS via SST en Docker op een VPS. Cloudflare is de opwindende nieuwkomer die maandelijks beter wordt.

Implementatiedoel: AWS met SST

Dit is het gouden pad. SST (Serverless Stack) heeft ingebouwde Next.js-ondersteuning aangedreven door OpenNext, en dit is waar de meeste engineering-inspanning is gegaan.

Architectuuroversicht

Wanneer je Next.js via SST op AWS implementeert, wordt hier het volgende gemaakt:

  • CloudFront-distributie — Je CDN, verwerkt statische activa en routering
  • Lambda-functie(s) — Server-side rendering, API-routes, server actions
  • S3-bucket — Statische activa, voorgerenderde pagina's, ISR-cache
  • DynamoDB-tabel — ISR-tagtoewijzing voor revalidatie
  • SQS-wachtrij — Asynchrone revalidatieverwerking
  • CloudFront Function of Lambda@Edge — Middleware-uitvoering

Klinkt als veel. Dat is het. Maar SST abstraheert dit allemaal in ongeveer 20 regels config.

SST-configuratie

Hier is een echte sst.config.ts van een van mijn productieprojecten:

/// <reference path="./.sst/platform/config.d.ts" />

export default $config({
  app(input) {
    return {
      name: "my-nextjs-app",
      removal: input.stage === "production" ? "retain" : "remove",
      home: "aws",
      providers: {
        aws: {
          region: "us-east-1",
        },
      },
    };
  },
  async run() {
    const site = new sst.aws.Nextjs("Site", {
      domain: {
        name: "myapp.com",
        dns: sst.aws.dns(),
      },
      warm: 5, // keep 5 Lambda instances warm
      memory: "1024 MB",
      environment: {
        DATABASE_URL: process.env.DATABASE_URL!,
        NEXT_PUBLIC_API_URL: "https://api.myapp.com",
      },
    });

    return {
      url: site.url,
    };
  },
});

Implementeer vervolgens:

npx sst deploy --stage production

Eerste implementatie duurt 8-12 minuten (CloudFront-distributie-propagatie). Volgende implementaties zijn 2-4 minuten.

Lambda-overwegingen

De grootste valkuil bij Lambda-gebaseerde hosting zijn koude starts. Next.js-serverfuncties zijn niet klein — je kijkt naar 20-80MB bundels afhankelijk van je dependencies. Koude starts variëren van 800ms tot 3 seconden.

Risico's die ik heb gebruikt:

  1. Ingerichte gelijktijdigheid — SST's warm parameter houdt instances warm. Bij $0.0000041667 per GB-seconde kost het warm houden van 5 instances van een 1GB-functie ongeveer $15/maand.
  2. Kleinere bundels — Controleer je server-side dependencies. Ik vond een project dat lodash server-side importeerde terwijl we alleen lodash/get nodig hadden. Bundle viel van 68MB naar 31MB.
  3. Regionale implementatie — Gebruik Lambda@Edge niet voor SSR tenzij je het absoluut nodig hebt. Single-region Lambda met CloudFront-caching is prima voor 95% van de apps.

OpenNext: Self-Host Next.js on AWS, Cloudflare, or VPS Without Vercel - architecture

Implementatiedoel: Cloudflare Workers

Cloudflare doet serieuze stappen. Hun Workers-runtime ondersteunt nu genoeg Node.js-API's zodat Next.js daar daadwerkelijk kan draaien, en de OpenNext Cloudflare adapter is opmerkelijk stabiel geworden.

Setup met OpenNext Cloudflare

npm install @opennext/cloudflare

Voeg toe aan je wrangler.toml:

name = "my-nextjs-app"
main = ".open-next/worker.js"
compatibility_date = "2025-01-01"
compatibility_flags = ["nodejs_compat_v2"]

[assets]
directory = ".open-next/assets"
binding = "ASSETS"

[[kv_namespaces]]
binding = "NEXT_CACHE_KV"
id = "your-kv-namespace-id"

Build en implementeer:

npx @opennext/cloudflare build
npx wrangler deploy

De Cloudflare-afwegingen

Voordelen:

  • Geen koude starts — Workers starten in onder 5ms globaal op
  • Globale edge standaard — Je SSR draait op 300+ locaties
  • Krankzinnige prijzen — $5/maand voor 10 miljoen requests op het betaalde plan

Nadelen:

  • Geheugenlimieten — 128MB gratis, 256MB betaald. Grote Next.js-apps kunnen dit raken.
  • CPU-tijdlimieten — 30 seconden op betaald plan. Zware SSR-pagina's kunnen een probleem zijn.
  • Node.js-compatibiliteitstekorten — Meeste dingen werken, maar als je native Node-modules zoals sharp direct gebruikt, heb je workarounds nodig. Cloudflare Images kan optimalisatie in plaats daarvan afhandelen.
  • Sommige Next.js-functies worden niet ondersteund — Tot begin 2025 is ondersteuning voor gedeeltelijke prerendering nog steeds experimenteel op Cloudflare.

Voor content-zware sites en marketingpagina's is Cloudflare Workers ongelooflijk aantrekkelijk. Voor complexe webapps met zware server-side logica zou ik nog steeds AWS of Docker voorkeuren.

Implementatiedoel: VPS met Docker

Soms wil je gewoon een server. Geen Lambda-functies, geen edge-runtime, geen 47-service-architectuurdiagram. Een doos die je code uitvoert. Ik respecteer dat.

De Dockerfile

Hier is de production Dockerfile die ik gebruik. Het is multi-stage, geoptimaliseerd en werkt daadwerkelijk:

# Stage 1: Dependencies
FROM node:20-alpine AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
COPY package.json pnpm-lock.yaml ./
RUN corepack enable pnpm && pnpm install --frozen-lockfile

# Stage 2: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .

ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production

RUN corepack enable pnpm && pnpm build

# Stage 3: Production
FROM node:20-alpine AS runner
WORKDIR /app

ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1

RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static

USER nextjs

EXPOSE 3000
ENV PORT=3000
ENV HOSTNAME="0.0.0.0"

CMD ["node", "server.js"]

Kritiek: je hebt output: 'standalone' nodig in je next.config.js:

/** @type {import('next').NextConfig} */
const nextConfig = {
  output: 'standalone',
};

module.exports = nextConfig;

VPS-aanbevelingen

Ik heb deze setup op verschillende providers gedraaid:

Provider Spec Maandelijks kosten Opmerkingen
Hetzner CAX21 4 vCPU ARM, 8GB RAM €7,49 (~$8) Beste waarde, EU datacenters
DigitalOcean Droplet 2 vCPU, 4GB RAM $24 Goede VS-dekking
Fly.io (machine) 2 vCPU, 4GB RAM ~$30 Auto-scaling, globale regio's
Railway Op basis van gebruik $5-50 Gemakkelijkste setup, Vercel-achtige DX
AWS EC2 t4g.medium 2 vCPU, 4GB RAM ~$25 Al op AWS

Voor een eenvoudige Docker-implementatie is Hetzner absurd goed in waarde. Ik draai een Next.js-app met 2M+ paginaweergaven/maand op een €7,49 Hetzner ARM-instance achter Cloudflare's gratis CDN-tier. De server heeft nauwelijks moeite.

Wat je verliest met Docker/VPS

Laten we eerlijk zijn over wat next start op een VPS je niet geeft in vergelijking met Vercel of de SST-setup:

  • ISR-revalidatie is basisvaardigheden — Alleen bestandssysteem-cache. Geen gedistribueerde cache over meerdere instances. Als je één server draait, is dit prima. Meerdere servers? Je hebt Redis of een gedeelde cachelaag nodig.
  • Geen edge middleware — Middleware draait in-process, wat volkomen prima is voor de meeste use cases.
  • Afbeeldingsoptimalisatie — Werkt via Sharp, maar je serveert geoptimaliseerde afbeeldingen van je enkele origin. Zet Cloudflare of een CDN ervoor.
  • Geen atomaire implementaties — Je moet zero-downtime implementaties zelf afhandelen (Docker Compose met health checks, of een reverse proxy zoals Caddy/Traefik).

Voor de meeste apps op Social Animal, vooral de headless CMS-builds die we doen via ons headless CMS-ontwikkelingwerk, is een enkele VPS met een CDN ervoor volkomen toereikend.

Kostenvergelijking: Vercel versus zelf-gehost

Laten we het hebben over geld. Dit is gebaseerd op echte factureringsgegevens van een Next.js-app met ~5M requests/maand met ISR, afbeeldingsoptimalisatie en gematigde server-side rendering.

Kostenfactor Vercel Pro Vercel Enterprise AWS/SST Cloudflare Hetzner VPS
Basisplatform $20/gebruiker/ma Aangepast (~$3k+/ma) $0 $5/ma €7,49/ma
Compute/requests $150-400/ma Inbegrepen $40-80/ma $0-15/ma Inbegrepen
Bandbreedte (100GB) Inbegrepen Inbegrepen $8,50 (CloudFront) Inbegrepen Inbegrepen
Afbeeldingsoptimalisatie $50-200/ma Inbegrepen $5-15/ma (Lambda) $5/ma (CF Images) Inbegrepen (Sharp)
ISR/Cache Inbegrepen Inbegrepen $2-5/ma (DynamoDB) $0-5/ma (KV) $0
Geschat totaal $300-700/ma $3.000+/ma $55-110/ma $10-25/ma $8-15/ma

Die Vercel-nummers zijn niet hypothetisch. Ik heb de facturen gezien. De per-seat pricing, function execution overages en bandbreedtekosten op Pro-tier stapelen zich snel op voor teams van 5+.

De AWS/SST-nummers gaan uit van gematigde verkeer met ingerichte gelijktijdigheid. Cloudflare's prijzen zijn werkelijk wild — het is moeilijk om echt geld daar uit te geven tenzij je iets exotisch doet.

Wanneer Vercel verlaten

Verlaat niet alleen omdat je kunt. Verlaat omdat je moet. Hier is mijn raamwerk:

Blijf op Vercel als:

  • Je team klein is (1-3 developers) en de tijd van developers je duurste bron is
  • Je minder dan $100/maand aan Vercel uitgeeft
  • Je niemand hebt die van infrastructuurwerk houdt
  • Je snel itereert en directe previews voor elke PR nodig hebt
  • Je Vercel-specifieke functies gebruikt zoals Analytics, Speed Insights, of Vercel AI SDK-integraties

Verlaat Vercel als:

  • Maandelijkse rekening overschrijdt $500 en groeit
  • Je infrastructuur in specifieke regio's nodig hebt voor compliance (GDPR, data residency)
  • Je al significante AWS/GCP/Cloudflare-infrastructuur draait
  • Koude starts op serverless zijn onaanvaardbaar voor je use case
  • Je aangepaste cachingstrategieën nodig hebt die niet in Vercel's model passen
  • Je Vercel's functiegrootteligmieten of uitvoeringstijdlimieten hebt bereikt

Overweeg serieus om te vertrekken als:

  • Je op Vercel Enterprise pricing bent en de contractverlenging komt eraan
  • Je app grotendeels statisch/ISR is en je betaalt prijzen voor dynamische SSR
  • Je je frontend samen met je backend in dezelfde infrastructuur wilt uitvoeren

Het migratieplan

Ik heb dit nu drie keer gedaan. Hier is het proces dat ik volg, verfijnd via pijnlijke ervaring.

Stap 1: Controleer je Next.js-functies

Voordat je iets aanraakt, catalogiseer welke Next.js-functies je werkelijk gebruikt:

# Find middleware
find . -name "middleware.ts" -o -name "middleware.js"

# Find API routes
find ./app -name "route.ts" -o -name "route.js" | head -20

# Check for ISR
grep -r "revalidate" ./app --include="*.ts" --include="*.tsx" | head -20

# Check for server actions
grep -r "use server" ./app --include="*.ts" --include="*.tsx" | head -20

# Check next.config for special features
cat next.config.js

Stap 2: Kies je doel

Op basis van de controle:

  • Zware ISR + middleware + afbeeldingsoptimalisatie → AWS/SST
  • Eenvoudige SSR + content site → Cloudflare of VPS
  • Al Docker/K8s infrastructuur → VPS/Docker
  • Moet het vrijdag af zijn → Docker op Railway of Fly.io

Als je bouwt met Next.js of Astro, beïnvloedt de keuze van het doelplatform je architectuurbeslissingen aanzienlijk.

Stap 3: Stel CI/CD in

Vercel's CI/CD is werkelijk geweldig. Je zult het missen. Repliceert het met GitHub Actions:

# .github/workflows/deploy.yml
name: Deploy
on:
  push:
    branches: [main]

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: pnpm/action-setup@v4
        with:
          version: 9

      - uses: actions/setup-node@v4
        with:
          node-version: 20
          cache: 'pnpm'

      - run: pnpm install --frozen-lockfile
      - run: pnpm build
      - run: pnpm test

      # For SST:
      - run: npx sst deploy --stage production
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}

      # For Docker/VPS (alternative):
      # - run: docker build -t myapp .
      # - run: docker push registry.example.com/myapp:latest
      # - run: ssh deploy@server 'cd /app && docker compose pull && docker compose up -d'

Stap 4: Implementaties voorbeeld

Dit is het ene wat mensen het meest missen van Vercel. Voor SST, gebruik stages:

# In your PR CI workflow
npx sst deploy --stage pr-${{ github.event.pull_request.number }}

Voor Docker, tools zoals Coolify (zelf-gehost) of Railway verwerken preview implementaties goed.

Stap 5: DNS-cutover

Het werkelijke migratieapparaat. Ik raad altijd aan:

  1. Implementeer op nieuwe infrastructuur naast Vercel
  2. Test grondig met een staging domein
  3. Verlaag DNS TTL tot 60 seconden een dag daarvoor
  4. Snijd DNS tijdens weinig verkeersuren
  5. Houd Vercel-implementatie 48 uur als fallback draaiende
  6. Controleer foutpercentages, TTFB en Core Web Vitals nauw

Stap 6: Verwijder Vercel

Zodra je zeker bent (geef het minstens een week), annuleer je het Vercel-abonnement en verwijder je het project. Laat geen zombieprojecten achter die kosten ophopen.

Veelvoorkomende valkuilen en hoe deze te vermijden

Omgevingsvariabelen verdwijnen. Next.js heeft NEXT_PUBLIC_ voorgevoegde variabelen (gebundeld op buildtijd) en server-only variabelen (beschikbaar op runtime). Op Vercel is dit onderscheid enigszins vaag. Bij zelf-gehost is het strikt. Zorg ervoor dat alle NEXT_PUBLIC_ variabelen op buildtijd beschikbaar zijn in je CI.

ISR-cache blijft niet bestaan. Op Docker moet de .next/cache map op een persistent volume staan. Anders verliest je cache elke keer dat je container opnieuw start:

# docker-compose.yml
services:
  web:
    build: .
    ports:
      - "3000:3000"
    volumes:
      - next-cache:/app/.next/cache

volumes:
  next-cache:

Sharp-installatiefouten. De sharp afbeeldingsoptimalisatiebibliotheek heeft platformspecifieke binaries nodig. In Docker, zorg ervoor dat je dependencies installeert binnen dezelfde architectuur als je runtime. De Dockerfile hierboven verwerkt dit met multi-stage builds met dezelfde basisimage.

Middleware-gedragsverschillen. Vercel draait middleware op hun edge-netwerk. Op AWS/SST draait het als een CloudFront Function (beperkt tot 10ms uitvoering, 2MB grootte). Complexe middleware moet mogelijk naar de serverfunctie worden verplaatst. Ik heb auth middleware moeten refactoreren vanwege deze limieten.

Ontbrekende headers en herschrijvingen. Als je vertrouwde op vercel.json voor headers, omleidingen of herschrijvingen, moet je deze naar next.config.js verplaatsen of je CDN/reverse proxy configuratie.

Als dit allemaal overweldigend aanvoelt, dat is precies het soort infrastructuurwerk dat we bij Social Animal aanpakken. Bekijk onze prijzen of neem contact op — we hebben deze migraties genoeg keren gedaan om een verfijnd proces te hebben.

Veelgestelde vragen

Is OpenNext productie-klaar in 2025? Ja. OpenNext v3.x draait productiewerklast voor duizenden bedrijven. Het SST/AWS-pad is het meest getest, met Cloudflare-ondersteuning dicht in de buurt. Ik zou de ondersteuning voor Google Cloud of bare Kubernetes niet rijp noemen, maar AWS en Cloudflare zijn solide.

Ondersteunt OpenNext Next.js App Router en Server Components? Volledige ondersteuning. App Router, Server Components, Server Actions, streaming en Suspense werken allemaal. Het OpenNext-team volgt Next.js-releases nauw, hoewel er meestal een vertraging van 1-3 weken is na grote Next.js-versies voordat OpenNext het opvangt.

Hoeveel kan ik werkelijk besparen door Vercel te verlaten? Het hangt sterk af van je gebruikspatronen. Voor een team van 5 developers dat een gematigde-traffic app draait, heb ik teams zien gaan van $600-800/maand op Vercel Pro naar $30-80/maand op AWS/SST of onder de $20/maand op een VPS. De besparingen zijn echt maar de extra onderhoudslast ook.

Kan ik ISR (Incremental Static Regeneration) zonder Vercel gebruiken? Absoluut. Op AWS/SST gebruikt ISR DynamoDB voor de tagcache en SQS voor asynchrone revalidatie — het is volledig functioneel inclusief on-demand revalidatie via revalidateTag() en revalidatePath(). Op een VPS werkt ISR met de bestandssysteem cache, wat prima is voor single-server implementaties.

Wat doen met Vercel's preview implementaties? Kan ik die repliceren? Je kunt 80% van de ervaring krijgen. SST ondersteunt stage-gebaseerde implementaties, dus elke PR kan zijn eigen stack krijgen. Coolify en vergelijkbare tools bieden preview implementaties voor Docker-gebaseerde setups. Wat je niet gemakkelijk kunt repliceren is Vercel's visuele commentaarsysteem en de nauwe GitHub-integratie voor implementatiestatus. De meeste teams vinden de afweging aanvaardbaar.

Moet ik OpenNext met Cloudflare of AWS gebruiken voor een headless CMS-site? Voor content-zware headless CMS-sites (Sanity, Contentful, Storyblok) is Cloudflare Workers een uitstekende keuze. Deze sites zijn meestal ISR-zwaar met relatief lichte server-side logica — perfect voor Cloudflare's prijsmodel. Ik zou alleen AWS kiezen als je functies nodig hebt die Cloudflare nog niet ondersteunt of als je al diep in het AWS-ecosysteem zit.

Is zelf-hosten van Next.js moeilijker dan zelf-hosten van Astro of Remix? Eerlijk gezegd? Ja. Next.js heeft de meest complexe builduitvoer van elk framework vanwege functies zoals ISR, middleware, afbeeldingsoptimalisatie en gedeeltelijke prerendering. Astro en Remix hebben veel eenvoudigere implementatiegegevens. Als je een nieuw project start en zelf-hosten is een prioriteit, overweeg Astro — het is dramatisch eenvoudiger te hosten. Maar als je al op Next.js bent, maakt OpenNext migratie praktisch.

Wat gebeurt er als OpenNext niet langer wordt onderhouden? OpenNext wordt ondersteund door SST en heeft een actieve gemeenschap met grote sponsors. Dat gezegd zijnde, dit is een legitiem bezorgdheid voor elke open-source afhankelijkheid. De matiging is dat de Docker/standalone benadering (next start) zonder OpenNext helemaal werkt — je verliest gewoon enkele van de meer geavanceerde functies zoals ISR-tag revalidatie en edge middleware. Het is een sierlijke degradatie, geen klif.