SvelteKit + PostgreSQL + Drizzle ORM
Production guidelines for SvelteKit form actions and load functions, Drizzle ORM over PostgreSQL, and Svelte 5 runes-based reactivity.
- Formats
- 4 files
- AGENTS.md
- 48 lines
- CLAUDE.md
- 16 lines
- Languages
- TypeScript
- Updated
- Sep 2026
- Used by
- 4 projects
Writes .claude/skills/sveltekit-postgres-drizzle/SKILL.md
$ curl -s --create-dirs -o .claude/skills/sveltekit-postgres-drizzle/SKILL.md https://stackitfast.com/rules/sveltekit-postgres-drizzle/SKILL.mdRule files
Works with Cursor · Claude Code · Windsurf · AGY
Architecture notes
Architecture Overview
Standardized production guidelines for SvelteKit (Svelte 5), Drizzle ORM, and PostgreSQL, built around SvelteKit’s server-first data loading and form action model.
Verified Real-World Adoption
The SvelteKit pattern shows up as the frontend layer in production self-hosted tools like Immich (photo management, SvelteKit + PostgreSQL + pgvector) and Open WebUI (AI interface, SvelteKit + FastAPI), with PocketBase built around the lighter-weight Svelte (non-Kit) equivalent.
Key Architectural Nuances
- Server-Only Import Boundary: SvelteKit enforces at build time that
$lib/server/*modules can’t leak into client-reachable code, making credential leaks a build failure instead of a runtime surprise. - Progressive Enhancement by Default: Form actions work without JavaScript and are enhanced with
use:enhance, unlike SPA patterns that require JS for any interaction to function at all.
Frequently asked questions
Does this AGENTS.md work with Cursor, Claude Code, and Windsurf?
Yes — AGENTS.md is the open, cross-tool standard read by Cursor, Claude Code, Windsurf, and 30+ other agents. A dedicated .mdc file is also included for Cursor's native .cursor/rules format.
Why must the Drizzle client only be imported from server files?
SvelteKit's `$lib/server` convention is a build-time guardrail: if server-only code (like a database client holding credentials) is imported into a module reachable from the client bundle, the build fails. Keeping the import chain strictly server-side avoids accidentally shipping the database connection string to the browser.
Why prefer form actions over client-side fetch for mutations?
Form actions work without JavaScript by default (the browser does a normal form POST), and `use:enhance` progressively upgrades them to an AJAX-like experience with optimistic UI when JS is available. A client-side fetch call has no fallback if JS fails to load or errors, and requires manually wiring a separate +server.ts endpoint.
Do I need to self-host PostgreSQL for this stack?
No — point DATABASE_URL at a managed provider like Supabase or Neon and skip database operations entirely; both have a free tier that's more than enough for a solo project or early-stage small team. Self-hosting Postgres only starts to make sense once you need full control over extensions, backups, or data residency.
Used in production
Explore all stackselekcsv
5Keeping parsing, compiled-validator generation, fuzzy column mapping and bitmap error tracking in one dependency-free core package lets every UI framework reuse identical import logic instead of six separate implementations.
crates.io
crates.io runs one pinned-dependency Rust binary as migrate, web and worker processes, splits domains into small internal crates, and generates its TypeScript client from OpenAPI types so the SvelteKit frontend and Axum API share one contract.
Open WebUI
A SvelteKit-plus-FastAPI split lets one Docker image serve the UI and API together, while SQLAlchemy over SQLite or PostgreSQL and a swappable vector-store layer let self-hosters scale from a laptop to a multi-worker Redis-backed deployment without changing code.
Immich
Machine-learning inference is split into its own FastAPI/Python service with pluggable CPU/GPU backends so heavy models stay off the request-serving NestJS process, while BullMQ and Redis move thumbnailing and job dispatch out of the request/response path.