---
title: "Building Without a DB Connection"
aliases: [payload-docker-build, nextjs-build-no-db, payload-production-build]
tags: [payloadcms, nextjs, docker, production, deployment, ssg, build]
sources: [raw/production__building-without-a-db-connection.md]
created: 2026-05-15
updated: 2026-05-15
---

## Problem

When building a Payload CMS site for production (especially in Docker), the build can fail because Next.js tries to statically generate pages that call the Payload Local API — which needs a live DB connection.

**Root cause:** Payload itself has no build-time DB requirement. The issue is Next.js SSG — enabled by default for any route that doesn't opt out or use a [Dynamic API](https://nextjs.org/docs/app/deep-dive/caching#dynamic-apis).

---

## Solutions

### 1. Two-phase build with `--experimental-build-mode`

Split the build into two steps:

```bash
# Step 1: compile only — no DB needed, no static generation
pnpm next build --experimental-build-mode compile

# Step 2: generate static pages — requires DB connection
pnpm next build --experimental-build-mode generate
```

**`compile` phase only** — if no DB is available at all:
```bash
# Inline NEXT_PUBLIC_ env vars without static generation
pnpm next build --experimental-build-mode generate-env
```

**Gotcha:** During `compile` mode, `NEXT_PUBLIC_*` env vars are **not inlined** — they will be `undefined` on the client. Use `generate` or `generate-env` to fix this.

---

### 2. Opt out of SSG globally (force-dynamic)

Add to every route segment file:

```ts
export const dynamic = 'force-dynamic'
```

> **Warning:** Disables static optimization — every page renders dynamically on each request. Use only if SSG is not needed.

More: [Next.js opt-out docs](https://nextjs.org/docs/app/deep-dive/caching#opting-out-2)

---

## Decision Matrix

| Situation | Solution |
|-----------|----------|
| Docker build, DB available at deploy time | Two-phase: `compile` then `generate` |
| Docker build, DB never available at build time | `compile` + `generate-env` |
| Static speed not a priority | `force-dynamic` on all routes |

---

## Key Takeaways

- Payload does not require a DB at build time — Next.js SSG does
- `--experimental-build-mode compile` skips static generation entirely
- `--experimental-build-mode generate` runs SSG separately when DB is available
- `--experimental-build-mode generate-env` handles `NEXT_PUBLIC_*` inlining without DB
- `force-dynamic` is a simple escape hatch but kills static optimization
- This is a common Docker CI/CD pain point — use the two-phase build as the default pattern

---

## Related

- [[wiki/payloadcms/local-api|Local API]] — the API that triggers the DB requirement during SSG
- [[wiki/payloadcms/local-api-outside-nextjs|Local API — Outside Next.js]] — standalone scripts with `getPayload`
- [[wiki/architecture/docker-compose|Docker Compose Patterns]] — Oliver Agency Docker conventions

---

## Sources

- `raw/production__building-without-a-db-connection.md`
- https://payloadcms.com/docs/production/building-without-a-db-connection
