All posts

28 Oct 2026 · Docker & Infra

Preventing next build OOM and SIGKILL on 2GB and 4GB VPS Instances

Why next build dies with SIGKILL on Hetzner CX22 and CX23, how swap and NODE_OPTIONS actually help, and when to stop building on the VPS.

next build is a memory hog. On a 2GB or 4GB VPS it often never finishes. The kernel sends SIGKILL. Docker reports exit 137. There is no TypeScript error. The box ran out of RAM.

AgenticPacks OSS is the Next.js app, Compose, and Postgres: Agentic-Packs/agenticpacks-oss. You can reproduce the OOM there on a small node. The production image, swap, and Hetzner path below are what Pro ships. See the standalone Docker Compose layout for the image itself.

What SIGKILL actually is

Node does not throw. The Linux OOM killer picks the fattest process and sends signal 9. next build compiles the App Router, webpack or Turbopack, and type checking in one process. Peak RSS on a Next.js 15 AI app with Prisma generate is often 1.5GB to 2.5GB. A CX22 with 2GB has nothing left after systemd, Docker, and Postgres.

Typical log:

Killed
ELIFECYCLE Command failed with exit code 137.

Inside Compose, the build container dies the same way if you run next build as a service command on that host.

Do not build in the running web container

The production image should already contain .next/standalone. You build in CI or on a larger builder, then copy the standalone output into a slim runner. That split is in the environment variable guide: ARG at build, secrets at runtime.

If you docker compose build on the 2GB VPS, you still pay the RAM on that box. Swap buys you a finish. It does not make the compile fast.

Add a swapfile before the first production build

On Debian or Ubuntu, as root:

fallocate -l 2G /swapfile
chmod 600 /swapfile
mkswap /swapfile
swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab

fallocate is faster than dd on ext4. Check with swapon --show and free -h. Two gigabytes of swap is enough for a Next.js 15 standalone build on 2GB RAM. Four gigabytes of RAM plus 2GB swap is comfortable.

Swap is disk. The build will crawl. That is still better than SIGKILL.

Cap Node, stop typecheck twice

export NODE_OPTIONS="--max-old-space-size=1536"
npx next build

On 2GB, 1536MB leaves room for the kernel. On 4GB, 3072 is fine.

next build already typechecks. Skip a separate tsc --noEmit in the same CI job unless you have a reason. Prisma generate before build, not inside a second Node heap.

Dockerfile builder stage:

ENV NODE_OPTIONS="--max-old-space-size=1536"
RUN npx prisma generate && npm run build

Do not raise the heap above physical RAM plus swap. Node will just OOM later and the killer will still fire.

When swap is the wrong fix

If every deploy builds on the VPS, you will fight this forever. Build the image in GitHub Actions on a hosted runner, push to a registry, and pull on the VPS. The node then only runs node server.js, Postgres, and Caddy. Resident RAM for a standalone Next process is a few hundred megabytes, not 2GB.

Pro does that path with Terraform and Compose on Hetzner. AgenticPacks OSS is the app you can still compose build locally on a laptop that has RAM.

Tired of watching next build die on a 4 euro VPS?

The MIT app and Compose file are on GitHub: Agentic-Packs/agenticpacks-oss.

For a Hetzner box that pulls a prebuilt image and never compiles on 2GB RAM, see the prebuilt image workflow in Pro.

Checklist

SymptomCauseFix
Exit 137, no stackOOM killer2GB swap, lower heap, or stop building on the VPS
Build hangs then diesSwap thrashBuild in CI, ship the image
Prisma generate plus next buildTwo heapsOne RUN in the builder
Postgres + build on same 2GBNo headroomStop Postgres during build, or do not build here

For the cost of running the app after it actually boots, see self-hosting architecture and cost.


Where to Go From Here

You do not have to keep compiling Next.js on the same 2GB node that serves production.

Option A: Free open-source baseline (MIT)

  • GitHub: github.com/Agentic-Packs/agenticpacks-oss
  • What is included: standalone Dockerfile, Compose, PostgreSQL 16, Auth.js v5, single-plan ($19/mo) Stripe checkout with webhooks and a credit counter. No Caddy. Build on a machine that has RAM.
  • Cost: free, MIT.

Option B: Ship with AgenticPacks Pro ($149 one-time)

If the VPS should only pull and run:

  • Automated Hetzner provisioning: terraform apply for the node, firewall, Caddy SSL, and Compose.
  • Production multi-agent core: LangGraph, pgvector RAG, Redis. Image built off-box.
  • Usage & Unit Economics: Stripe subscriptions, webhooks, and a token-to-dollar ledger.