
Bun.js + Elysia + Drizzle: eine typsichere REST-API mit PostgreSQL
Ein praktisches Bun.js-API mit Elysia für Routing, Drizzle ORM für typisierte SQL-Abfragen, PostgreSQL und Zod-Validierung.
Elysia verarbeitet HTTP-Routen, Drizzle beschreibt PostgreSQL-Tabellen mit TypeScript und Bun führt den gesamten Service ohne separaten Transpilierungsschritt aus.
Warum dieser Stack
Jede Bibliothek hat eine klare Aufgabe — das hält den Service testbar und erweiterbar.
Elysia
Ein Bun-natives HTTP-Framework mit Routen, Middleware und Schemas.
Drizzle
Ein SQL-first ORM: Tabellen sind TypeScript, Abfragen bleiben nah an SQL.
PostgreSQL
Ein zuverlässiges Production-Storage für Indizes, Transaktionen und Wachstum.
Zod
Validiert Eingaben an der API-Grenze vor der Service-Schicht.
Die Anfrage wird vor SQL validiert; die Antwort folgt einem typisierten Vertrag.
Screenshot des Abschnitts stackSchritt 1: Projekt erstellen
Bun installiert Abhängigkeiten und führt TypeScript ohne separaten Bundler aus.
Initialisieren
mkdir tasks-api && cd tasks-api
bun init
bun add elysia drizzle-orm postgres zod
bun add -d drizzle-kitUmgebung konfigurieren
DATABASE_URL=postgres://app:app@localhost:5432/tasks
PORT=3000
DB_POOL_SIZE=10Bun lädt .env automatisch. Geheimnisse gehören nicht ins Repository.
Migrationen konfigurieren
import { defineConfig } from "drizzle-kit";
export default defineConfig({ schema: "./src/db/schema.ts", out: "./drizzle", dialect: "postgresql", dbCredentials: { url: process.env.DATABASE_URL! } });Danach bun run db:generate und bun run db:migrate ausführen.
Schritt 2: Tabelle und Migration definieren
Die Tabelle ist die Quelle für Insert- und Select-Typen. Einen zweiten manuellen Task-Typ sollten wir vermeiden.
import { boolean, pgTable, text, timestamp, uuid } from "drizzle-orm/pg-core";
export const tasks = pgTable("tasks", { id: uuid("id").defaultRandom().primaryKey(), title: text("title").notNull(), done: boolean("done").notNull().default(false), createdAt: timestamp("created_at", { withTimezone: true }).defaultNow().notNull() });
export type Task = typeof tasks.$inferSelect;
export type NewTask = typeof tasks.$inferInsert;Die generierte Migration wird mit bun run db:migrate angewendet.
Schritt 3: typsichere Elysia-Routen
Elysia validiert Payloads am Rand der Anwendung. Der Handler kann sich dadurch auf die Datenbankoperation konzentrieren.
import { Elysia, t } from "elysia";
import { desc, eq } from "drizzle-orm";
import { db } from "./db/client";
import { tasks } from "./db/schema";
export const app = new Elysia()
.get("/health", () => ({ status: "ok", runtime: "bun" }))
.get("/tasks", () => db.select().from(tasks).orderBy(desc(tasks.createdAt)))
.patch("/tasks/:id", async ({ params, body }) => { const [task] = await db.update(tasks).set({ done: body.done }).where(eq(tasks.id, params.id)).returning(); return task ?? new Response("Nicht gefunden", { status: 404 }); }, { params: t.Object({ id: t.String() }), body: t.Object({ done: t.Boolean() }) })
.listen(Number(Bun.env.PORT ?? 3000));Database Client und Docker Compose
Erzeuge einen Pool pro langlebigem Bun-Prozess. Compose stellt lokal für das ganze Team dieselbe PostgreSQL-Version bereit.
import postgres from "postgres";
import { drizzle } from "drizzle-orm/postgres-js";
const sql = postgres(Bun.env.DATABASE_URL!, { max: Number(Bun.env.DB_POOL_SIZE ?? 10), prepare: false });
export const db = drizzle(sql);services:
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: app
POSTGRES_DB: tasks
ports: ["5432:5432"]Transaktionen, Fehler und Production-Regeln
Ein schneller Runtime ersetzt keine klaren Datengrenzen.
Transaktionen für verbundene Writes
Mehrere Tabellen mit db.transaction(async (tx) => { ... }) atomar ändern.
404 für fehlende Ressourcen
Das Ergebnis von returning() prüfen und nicht undefined mit 200 senden.
Migrationen separat ausführen
Migrationen als Deploy-Schritt anwenden, nicht aus jeder Server-Instanz.
Pool begrenzen
In Serverless-Umgebungen Pooler oder niedrigere Limits verwenden.
Handler ohne offenen Port testen
Mit handle lässt sich die Anwendung direkt testen.
import { expect, test } from "bun:test";
import { app } from "./index";
test("lehnt einen leeren Titel ab", async () => {
const response = await app.handle(new Request("http://localhost/tasks", { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ title: " " }) }));
expect(response.status).toBe(422);
});Mit bun test gegen eine eigene Testdatenbank ausführen.
Lokal ausführen und testen
PostgreSQL starten
docker compose up -d
bun run db:migrateBun starten
bun run src/index.ts
curl http://localhost:3000/healthLockfile verwenden
bun install --frozen-lockfile
bun run db:migrate
bun testFAQ
Ja. Drizzle funktioniert mit Bun und PostgreSQL über den postgres-Treiber oder einen unterstützten Treiber. Die verwendeten Versionen sollten im Deployment getestet werden.
Nein. Bun stellt Runtime, Package Manager und TypeScript-Ausführung bereit.
Fazit
Beschreiben Sie die Aufgabe — die ersten 15 Minuten der Beratung sind kostenlos.
Verwandte Artikel

AI Assistant Entwicklung Kosten 2026: RAG, Knowledge Base, Integrationen und Support
Praktischer Leitfaden zu Kosten fuer AI Assistants: RAG, Knowledge Base, Channels, Tool Use, Guardrails, Evaluations, Monitoring und Support.

KI fur Landingpage-Entwicklung: wo sie Launches beschleunigt und wo sie Conversion schadet
Eine praxisnahe Analyse zur Nutzung von KI fur Landingpages: v0, Webflow AI, Builder.io, Framer-ahnliche Builder, UX-Generierung, Copy, SEO, Personalisierung, A/B-Tests, Template-Risiken, Accessibility, Security und technischer Schuldenaufbau.

AI SEO / GEO im Jahr 2026: Ihre nächsten Kunden sind nicht Menschen — sondern Agents
Suche verschiebt sich von Klicks zu Antworten. Bots und AI-Agents crawlen, zitieren, empfehlen — und kaufen zunehmend. Erfahren Sie, was AI SEO / GEO bedeutet, warum klassisches SEO nicht mehr reicht und wie PAS7 Studio Marken im agentischen Web sichtbar macht.

Der leistungsstärkste Chip von Apple? M5 Pro und M5 Max brechen Rekorde
Eine Analyse zu Apple M5 Pro und M5 Max im März 2026. Wir zeigen, warum diese Chips als die stärksten professionellen Laptop-SoCs von Apple gelten können, wie sie sich gegen M4 Pro, M4 Max, M1 Pro, M1 Max schlagen und was der Vergleich mit aktuellen Intel- und AMD-Chips zeigt.
Professionelle Entwicklung für Ihr Geschäft
Wir erstellen moderne Web-Lösungen und Bots für Unternehmen. Erfahren Sie, wie wir Ihnen helfen können, Ihre Ziele zu erreichen.