Zuerst: Verwenden Sie das übergeordnete Skill neon für einen Neon-Überblick, Einstieg in Neon, Best Practices für die Entwicklung mit Neon und mehr.
Falls das Skill neon nicht installiert ist, rufen Sie es von https://neon.com/docs/ai/skills/neon/SKILL.md ab oder installieren Sie es mit:
npx skills add neondatabase/agent-skills --skill neon
Neon Functions
Dies ist eine öffentliche Beta-Funktion, die derzeit in us-east-2 und eu-central-1 verfügbar ist.
Neon Functions sind langlaufende Node.js-HTTP-Handler, die auf einem Neon-Branch bereitgestellt werden. Jede Funktion erhält eine öffentliche HTTPS-URL, läuft in derselben Region wie Ihre Datenbank und erhält – wenn der Branch Postgres hat – automatisch die DATABASE_URL injiziert. Sie stellen sie bereit und verwalten sie über dieselbe Neon-CLI, neon.ts und API, die Sie bereits verwenden.
Verwenden Sie dieses Skill, um dem Benutzer zu helfen, Funktionen zu definieren, lokal auszuführen, bereitzustellen und neben seiner Datenbank zu verwalten. Liefern Sie eine bereitgestellte Funktion mit ihrer Aufruf-URL, eine funktionierende lokale neon dev-Schleife oder eine präzise Antwort aus der offiziellen Neon-Dokumentation.
Wann verwenden
Greifen Sie zu Neon Functions, wenn die Arbeitslast ein Request/Response-Handler ist, der davon profitiert, am Leben zu bleiben und in der Nähe der Daten zu sein:
- Langlaufende Request/Response-Abläufe, die Lambda-ähnliche Limits überschreiten. Agenten, die mehrere LLM-Aufrufe und Tool-Invocationen pro Anfrage tätigen, oder Bild-/Video-Generierung, überschreiten routinemäßig die ~10–60s Ausführungslimits und kurzen Streaming-Fenster traditioneller serverloser Funktionen. Neon Functions sind langlaufend: Der Handler muss nur innerhalb von 15 Minuten mit der Antwort beginnen, und ein offener Stream bleibt am Leben, solange Bytes fließen. Das ist genug Spielraum für echte Agenten-Workloads.
- Stateful Streaming ohne Redis aufzusetzen. Da eine Funktion über eine Anfrage hinweg am Leben bleibt, kann sie einen SSE-Endpunkt oder einen WebSocket-Server hosten und die Verbindung im Prozess halten – kein externer Zustandsspeicher (Redis usw.) nötig, nur um einen Stream kohärent zu halten. Der Modul-Scope-Zustand (ein
pg-Pool, ein In-Memory-Zähler) bleibt über Anfragen auf demselben Isolat bestehen. - Berechnung, die neben Postgres liegen muss. Die Funktion läuft in derselben Region wie die Datenbank des Branches, sodass es keine regionsübergreifenden Roundtrips bei jeder Abfrage gibt.
DATABASE_URLwird für Sie injiziert. - Ein Backend, das mit Ihren Daten brancht. Jeder Branch führt seine eigene Version der Funktion unter seiner eigenen URL aus, gegen seine eigene isolierte Datenbank (und Speicher- und Gateway-) Zustand. Preview-Bereitstellungen, CI und Entwicklungsumgebungen erhalten jeweils ein eigenständiges Backend – das Bereitstellen auf einem Kind-Branch wirkt sich nie auf den Eltern-Branch aus.
- Webhooks, Bots und Post-Response-Arbeiten. Webhook-Handler, die in mehrere DB-Schreibvorgänge aufteilen, Discord/WebSocket-Bots und Fire-and-Forget-Nacharbeiten über
waitUntil(Analytik, Audit-Logs) passen alle. - Wiederkehrende HTTP-Arbeiten. Ein Function Trigger POSTet auf die Funktion per Cron (
type: "schedule"). Gleicherfetch-Handler, gleiches 15-Minuten-Limit für die erste Antwort. Siehe Function Triggers.
Wenn die Arbeitslast eine reine statische Site ist oder etwas, das außerhalb der unterstützten Regionen (us-east-2, eu-central-1) laufen muss, ist dies noch nicht das richtige Werkzeug (siehe Timeouts und Runtime-Limits und Verfügbarkeit).
Was es tut
- Langlaufend & serverlos – Entwickelt für WebSocket-Server (siehe WebSocket-Server), SSE-Endpunkte (siehe Server-Sent Events (SSE)), lange Agenten-HTTP-Streams und APIs. Skaliert im Leerlauf auf null.
- Web-Standard-Handler – Eine Funktion ist jeder Standard-Export mit einer
fetch(request)-Methode, die eineResponsezurückgibt (Workers/WinterTC-kompatibel). Eine Hono-App exportiert genau diese Form, also funktioniertexport default appsofort. Läuft auf Node.js 24, sodass alle Node-APIs verfügbar sind. - In der Nähe Ihrer Datenbank – Läuft in der Region des Branches;
DATABASE_URLwird automatisch injiziert, wenn der Branch Postgres hat. - Branchbar – Jeder Branch führt seine eigene Funktionsversion unter seiner eigenen URL gegen seinen eigenen isolierten Zustand aus.
- Gleiche CLI/API – Bereitstellung und Verwaltung über
neon,neon.tsoder die Neon-API. - Function Triggers – Neon POSTet per Cron auf die Funktion. Siehe Function Triggers.
Verfügbarkeit
Prüfen Sie diese Vorbedingung, bevor Sie etwas einrichten: Neon Functions ist eine öffentliche Beta-Funktion, die derzeit in us-east-2 und eu-central-1 verfügbar ist. Bestätigen Sie, dass das Neon-Projekt des Benutzers in einer dieser Regionen liegt. Die Nutzung von Functions wird während der öffentlichen Beta nicht abgerechnet.
Architektur: Wo Functions hingehören
Neon (einschließlich Functions) sind Backend-Primitives, kein Full-Stack-App-Hosting. Hosten Sie Ihre App auf Vercel (oder Netlify oder einem anderen Frontend/App-Host); Functions sind das langlaufende, zustandsbehaftete Stück Ihres Backends, das neben Ihren Daten lebt. Sie komponieren mit dieser Plattform auf zwei Arten:
- Fügen Sie eine Function zu einer Full-Stack-App hinzu. Ihre Next.js / TanStack Start App auf Vercel (oder Netlify) besitzt UI, Authentifizierung (z.B. Neon Auth) und kommuniziert direkt mit Lakebase Postgres und Object Storage. Wenn eine Arbeitslast die kurzen serverlosen Limits des Hosts überschreitet – ein WebSocket- oder SSE-Server oder ein langlaufender Agent, der ein Timeout verursachen würde – verschieben Sie nur dieses Stück auf eine Neon Function. (Siehe Functions als Agent-Backend für das Client-direkt-Muster.)
- Betreiben Sie die gesamte Backend-Steuerungsebene auf Functions. Besonders wenn das Frontend Client-seitig ist – TanStack Router, React Router im Client-Modus und ähnliche SPAs, die auf Vercel oder Netlify gehostet werden – ruft der Client Functions direkt auf. Bauen Sie REST-APIs und Request/Response-Agenten, hosten Sie MCP-Server und führen Sie alles Zustandsbehaftete oder was in der Nähe von Postgres und Object Storage sein sollte.
Sichern Sie eine Function in beiden Fällen wie jede eigenständige REST-API: Überprüfen Sie einen JWT oder API-Key am Anfang des Handlers (siehe WARNUNG unter Functions als Agent-Backend). Da eine Function nur Ihr Backend ist, können Sie Teile zwischen Ihrem Host und Neon verschieben – verlegen Sie einen Agenten oder einen zustandsbehafteten WebSocket-Server auf eine Function, wenn er mehr Laufzeit benötigt, und bei Bedarf zurück.
Einrichtung
Functions werden in neon.ts deklariert (siehe das neon-Skill für den Branch-First-Workflow und neon.ts-Grundlagen). Fügen Sie @neon/config hinzu und deklarieren Sie Functions unter preview.functions, keyed by Slug:
// neon.ts
import { defineConfig } from "@neon/config/v1";
export default defineConfig({
preview: {
functions: {
todos: {
// slug: ^[a-z0-9]{1,20}$ - Kleinbuchstaben/Ziffern, keine Bindestriche
name: "todo api", // nur Anzeigebezeichnung
source: "src/index.ts", // Einstiegsdatei, relativ zu neon.ts
},
},
},
});
Der Slug ist die permanente Identität der Funktion (er erscheint in der Aufruf-URL und CLI-Befehlen) und kann nach der ersten Bereitstellung nicht mehr geändert werden. Verwenden Sie name für eine menschenlesbare Bezeichnung.
Eine minimale Funktion – eine Hono-App, die über die injizierte DATABASE_URL das Postgres des Branches abfragt:
// src/index.ts
import { Hono } from "hono";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { parseEnv } from "@neon/env";
import { attachDatabasePool } from "@neon/functions";
import config from "../neon";
import { todos } from "./db/schema";
const env = parseEnv(config);
const pool = new Pool({ connectionString: env.postgres.databaseUrl, max: 5 });
attachDatabasePool(pool);
const db = drizzle(pool);
const app = new Hono();
app.get("/", (c) => c.text("Neon + Hono + Drizzle"));
app.post("/todos", async (c) => {
const { text } = await c.req.json<{ text: string }>();
const [row] = await db.insert(todos).values({ text }).returning();
return c.json(row, 201);
});
app.get("/todos", async (c) => c.json(await db.select().from(todos)));
export default app;
Erstellen Sie den pg-Pool im Modul-Scope (wiederverwendet über Anfragen auf demselben Isolat) und halten Sie max klein (z.B. 5), da jedes Isolat seinen eigenen Pool behält. Rufen Sie attachDatabasePool(pool) auf, damit eine im Leerlauf getrennte Verbindung keine uncaughtException verursacht – siehe Verbindung zu Postgres.
parseEnv(config) erfordert jede Variable, die die Konfiguration impliziert. Eine Funktion, die nur über die gepoolte URL mit Postgres spricht, kann auf nur diesen Schlüssel eingegrenzt werden – parseEnv validiert dann und gibt nur das zurück, was Sie angefordert haben (die Schlüssel werden automatisch vervollständigt aus Ihrer neon.ts):
const { postgres } = parseEnv(config, ["DATABASE_URL"]); // nicht die ungepoolte URL, Auth usw.
const pool = new Pool({ connectionString: postgres.databaseUrl, max: 5 });
attachDatabasePool(pool);
Lokal entwickeln und bereitstellen
neon dev # bedient jede Funktion in neon.ts mit Hot Reload; injiziert DATABASE_URL & Co.
neon deploy --env <datei> # bevorzugte vollständige Bereitstellung von neon.ts; --env ist die Datei, aus der die Funktions-Umgebung gelesen wird
Halten Sie .env oder .env.local mit jedem Schlüssel unter preview.functions.*.env auf dem neuesten Stand. neon env pull schreibt nur von Neon verwaltete Variablen; fügen Sie Funktions-Geheimnisse zu dieser Datei hinzu und übergeben Sie sie als --env. neon deploy --env <datei> lädt diese Datei jedes Mal in process.env und lädt dann diese Werte hoch. Ein fehlender Wert ist undefined und defineConfig wirft einen Fehler. Lassen Sie den Schlüssel aus neon.ts weg, wenn Sie ihn nicht schreiben möchten. Zwingen Sie niemals einen fehlenden process.env-Wert zu einem leeren String (das lädt "" hoch und löscht den Live-Key). Eine leere Zuweisung (KEY=) ist ebenfalls "". Verwenden Sie process.env.X!, wenn TypeScript eine Zusicherung benötigt.
Um eine einzelne Funktion bereitzustellen, ohne neon.ts anzuwenden: neon functions deploy <slug> --src src/index.ts (--src akzeptiert entweder die Einstiegsdatei oder ein Verzeichnis, das index.ts, index.mjs oder index.js enthält). Das --env dieses Befehls ist KEY=VALUE (wiederholbar), kein Dateipfad. Verwenden Sie es für eine gezielte Umgebungsaktualisierung. Rufen Sie die öffentliche URL mit neon functions get <slug> ab (das Feld invocation_url, in der Form https://<branch_id>-<slug>.compute.<cell>.us-east-2.aws.neon.tech). Verwalten Sie mit neon functions list|get|delete.
Wenn neon checkout einen neuen Branch erstellt und eine neon.ts vorhanden ist, wird die Richtlinie automatisch angewendet. Dieses Erstellen-Anwenden lädt kein --env. Wenn die Funktions-Umgebung process.env liest, führen Sie nach dem Checkout neon deploy --env <datei> aus (fügen Sie --update-existing hinzu, wenn der Checkout den Branch bereits erstellt hat). Das Auschecken eines bestehenden Branches stellt nicht erneut bereit; führen Sie explizit neon deploy --env <datei> aus.
Neon Infrastructure as Code (neon.ts)
Der Block preview.functions aus Einrichtung ist Teil von neon.ts, der Infrastructure-as-Code-Datei von Neon – eine TypeScript-Datei deklariert jede Funktion (ihre source, ihren Anzeige-name und env) zusammen mit allen anderen Branch-Diensten, in der Versionskontrolle (siehe das neon-Skill für die vollständige Referenz). Behandeln Sie es wie Terraform für Ihren Branch:
neon config status # die Live-Konfiguration des Branches ausgeben (bereitgestellte Funktionen)
neon config plan # Dry-Run-Diff dessen, was apply ändern würde
neon config apply --env <datei> # bündeln + die deklarierten Funktionen bereitstellen (neon deploy ist ein Alias; übergeben Sie --env, wenn die Funktions-Umgebung process.env liest)
Functions sind Branch-bezogen: Jeder Branch führt seine eigene Bereitstellung unter seiner eigenen URL aus. Wenn eine neon.ts vorhanden ist, wendet neon checkout die Richtlinie an, während es einen Branch erstellt. Dieses Erstellen-Anwenden lädt kein --env. Wenn die Funktions-Umgebung process.env liest, führen Sie nach dem Checkout neon deploy --env <datei> aus. Das Auschecken eines bestehenden Branches stellt nicht erneut bereit – führen Sie neon deploy --env <datei> aus, um Änderungen anzuwenden.
Die pro-Branch-Bereitstellungsoptimierung (z.B. runtime) lebt im branch-Closure, keyed by Slug, sodass sie je nach Branch variieren kann, ohne zu ändern, welche Funktionen existieren:
export default defineConfig({
preview: {
functions: { todos: { name: "todo api", source: "src/index.ts" } },
},
branch: (branch) => ({
preview: { functions: { todos: { runtime: "nodejs24" } } },
}),
});
Umgebungsvariablen
Neon injiziert Branch-bezogene Verbindungsstrings und Dienst-URLs zur Laufzeit – Sie deklarieren diese nicht oder übergeben sie zur Bereitstellungszeit nicht:
| Variable | Hinweise |
|---|---|
NEON_BRANCH | Der Name des Branches (z.B. main, preview/foo). In jeden Branch injiziert, einschließlich des Standard-Branches. |
DATABASE_URL | Gepoolter Verbindungsstring. Für die meisten Abfragen verwenden. Nur vorhanden, wenn der Branch Postgres hat. |
DATABASE_URL_UNPOOLED | Direkte Verbindung. Für Migrationen, LISTEN/NOTIFY, Multi-Roundtrip-Transaktionen verwenden. |
NEON_AUTH_BASE_URL | Vorhanden, wenn Neon Auth auf dem Branch aktiviert ist. |
NEON_DATA_API_URL | Vorhanden, wenn die Data API auf dem Branch aktiviert ist. |
Object Storage (AWS_*) und AI Gateway (NEON_AI_GATEWAY_*)-Variablen werden ebenfalls injiziert, wenn diese Dienste deklariert sind – siehe die Skills neon-object-storage und neon-ai-gateway.
neon env pull / neon-env run / neon dev geben NEON_BRANCH (und die Verbindungsstrings) auch in Ihre lokale Entwicklungsumgebung aus, sodass lokale Läufe die bereitgestellte Laufzeit spiegeln.
Ihre eigenen Geheimnisse sind pro Bereitstellung. Bevorzugter Weg: Deklarieren Sie sie in neon.ts und führen Sie neon deploy --env <datei> aus. <datei> ist die git-ignorierte Datei, die env pull bereits schreibt (.env, wenn diese Datei existiert, andernfalls .env.local). Env pull schreibt nur von Neon verwaltete Variablen; fügen Sie Funktions-Geheimnisse zu dieser Datei hinzu. Alle deklarierten Funktions-Umgebungsschlüssel müssen vorhanden sein. Lassen Sie einen Schlüssel aus neon.ts weg, wenn Sie ihn nicht schreiben möchten. undefined bedeutet, dass Sie den Schlüssel schreiben wollten und der Wert fehlt (defineConfig wirft einen Fehler). Zwingen Sie niemals einen fehlenden process.env-Wert zu einem leeren String: das lädt "" hoch und löscht den Live-Key. Eine leere Zuweisung in der Datei (KEY=) ist ebenfalls "". Wenn TypeScript eine Zusicherung benötigt, verwenden Sie `process.env