Skip to content
infra-ts is early and moving fast.npm
infra-ts
Esc
navigateopen⌘Jpreview

Neon

Shared Neon projects with environment-scoped branches.

@infra-ts/neon provides a lightweight project definition. Its runtime is hybrid: project identity is stack-shared and branch identity is scoped to each logical environment.

import { buildNeonProject } from "@infra-ts/neon";

export const database = buildNeonProject({
	projectName: "my-app-db",
	orgId: "org-example",
	region: "aws-us-east-2",
	pgVersion: 17,
	database: "neondb",
	role: "neondb_owner",
	branchName: (environment) => `app-${environment.name}`,
	branch: (target, environment) => ({
		...target,
		...(environment.stage === "preview"
			? { expiresAt: "2027-01-01T00:00:00Z" }
			: {}),
	}),
});

Production selects and revalidates the API-confirmed project default branch. Non-production uses a sanitized prefix plus deterministic hash whenever the logical name changes or truncates, then applies pure tuning. Runtime state stores project ID, branch ID/name, and ownership default|managed; it never adopts by name.

Immutable project drift and branch name/default/protected/parent/expiry drift produce structured blocking conflicts. In-place branch updates are not implemented; removing an existing expiry is therefore detected and blocked.

The static env contract exposes sensitive, managed, recreatable:

  • pooled DATABASE_URL
  • direct DATABASE_URL_UNPOOLED

Checkout fetches URLs only from the selected stored branch. The REST adapter provisions a read-write endpoint with each preview, paginates branches, retries mutation locks, and waits only operation IDs returned by the initiating mutation, scanning pagination as needed. Historical failed operations do not block new work.

cleanupNeonEnvironment deletes only a stored managed branch after the API confirms it is neither default nor protected. Checkout and Git prune never call cleanup. Project destroy deletes remote first and then tombstones all definition state. Created-resource CAS losers clean up only their exact IDs and return recoverable partial identity if cleanup fails. Missing stored projects use a fenced replacement reservation. Delete state is retained until bounded polling confirms remote absence. Project destroy is stack-reserved and rechecks its exact project identity before tombstoning, so a concurrent replacement is not orphaned or erased.

Credentials come from NEON_API_KEY or an authenticated Neon CLI session. CLI-session 401 refresh runs once with output suppressed. Connection strings never enter state.

Was this page helpful?