Neon Functions
Ceci est une fonctionnalité en aperçu et disponible uniquement dans us-east-2. Neon Functions sont des gestionnaires HTTP Node.js long-running déployés sur une branche Neon. Chaque fonction obtient une URL HTTPS publique, s'exécute dans la même région que votre base de données, et — si la branche a Postgres — obtient DATABASE_URL injecté automatiquement. Vous les déployez et les gérez via le même Neon CLI, neon.ts et API que vous utilisez déjà.
Utilisez cette skill pour aider l'utilisateur à définir, exécuter localement, déployer et gérer des fonctions à côté de sa base de données. Livrez une fonction déployée avec son URL d'invocation, une boucle neonctl dev fonctionnelle, ou une réponse précise depuis la documentation officielle de Neon.
When to Use
Recourez à Neon Functions quand la charge de travail est un gestionnaire request/response qui bénéficie de rester actif et proche des données :
- Des flux request/response long-running qui dépassent les limites de type lambda. Les agents qui effectuent plusieurs appels LLM et invocations d'outils par requête, ou la génération d'images/vidéos, dépassent régulièrement les limites d'exécution de ~10–60s et les fenêtres de streaming courtes des fonctions serverless traditionnelles. Neon Functions sont long-running : le gestionnaire doit juste commencer à répondre dans les 15 minutes, et un flux ouvert reste actif tant que les bytes continuent de s'écouler. C'est assez d'espace pour les charges de travail d'agent réelles.
- Streaming avec état sans ajouter Redis. Parce qu'une fonction reste active pendant une requête, elle peut héberger un endpoint SSE ou un serveur WebSocket et maintenir la connexion ouverte en processus — aucun magasin d'état externe (Redis, etc.) nécessaire juste pour garder un stream cohérent. L'état au niveau du module (un pool
pg, un compteur en mémoire) persiste entre les requêtes sur le même isolate. - Compute qui doit être près de Postgres. La fonction s'exécute dans la même région que la base de données de la branche, donc pas de round trips entre régions à chaque requête.
DATABASE_URLvous est injecté. - Un backend qui se branche avec vos données. Chaque branche exécute sa propre version de la fonction à sa propre URL, contre sa propre état isolé de base de données (et stockage, et gateway). Les déploiements en aperçu, CI et environnements de dev obtiennent chacun un backend autonome — déployer sur une branche enfant n'affecte jamais le parent.
- Webhooks, bots et travaux post-réponse. Les gestionnaires de webhook qui fanoutent en plusieurs écritures DB, les bots Discord/WebSocket, et les tâches fire-and-forget via
waitUntil(analyses, journaux d'audit) conviennent tous.
Si la charge de travail est un site statique pur, un travail cron/background qui a besoin de son propre cycle de vie et annulation, ou quelque chose qui doit s'exécuter en dehors de us-east-2 aujourd'hui, ce n'est pas le bon outil pour l'instant (voir Timeouts et Availability ci-dessous).
What It Does
- Long-running & serverless — Construit pour les serveurs WebSocket, les endpoints SSE, les longs streams HTTP d'agent, et les APIs. Toujours capable de scaler à zéro quand inactif.
- Gestionnaire web-standard — Une fonction est n'importe quel export par défaut avec une méthode
fetch(request)renvoyant uneResponse(compatible Workers/WinterTC). Une app Hono exporte exactement cette forme, doncexport default appfonctionne. S'exécute sur Node.js 24, donc toutes les APIs Node sont disponibles. - Proche de votre base de données — S'exécute dans la région de la branche ;
DATABASE_URLinjecté automatiquement quand la branche a Postgres. - Branchable — Chaque branche exécute sa propre version de la fonction à sa propre URL contre son propre état isolé.
- Même CLI/API — Déployez et gérez via
neonctl,neon.tsou l'API Neon.
Setup
Les fonctions sont déclarées dans neon.ts (voir la skill neon pour le workflow branch-first et les bases de neon.ts). Ajoutez @neondatabase/config et déclarez les fonctions sous preview.functions, indexées par slug :
// neon.ts
import { defineConfig } from "@neondatabase/config/v1";
export default defineConfig({
preview: {
functions: {
todos: {
// slug: ^[a-z0-9]{1,20}$ — lowercase letters/digits, no hyphens
name: "todo api", // display label only
source: "src/index.ts", // entry file, relative to neon.ts
},
},
},
});
Le slug est l'identité permanente de la fonction (il apparaît dans l'URL d'invocation et les commandes CLI) et ne peut pas être changé après le premier déploiement. Utilisez name pour un label lisible par l'humain.
Une fonction minimale — une app Hono qui interroge le Postgres de la branche via DATABASE_URL injecté :
// src/index.ts
import { Hono } from "hono";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { parseEnv } from "@neondatabase/env/v1";
import config from "../neon";
import { todos } from "./db/schema";
const env = parseEnv(config);
const pool = new Pool({ connectionString: env.postgres.databaseUrl, max: 5 });
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;
Ceci est l'exemple with-hono, vérifié de bout en bout. Créez le pool pg au niveau du module (réutilisé entre les requêtes sur le même isolate) et gardez max petit (ex. 5), puisque chaque isolate garde son propre pool.
Develop locally and deploy
neonctl dev # serves every function in neon.ts with hot reload; injects DATABASE_URL & friends
neonctl deploy # bundles with esbuild, uploads, and applies neon.ts to the linked branch
Pour déployer une seule fonction sans neon.ts : neonctl functions deploy <slug> --path . --entry src/index.ts. Récupérez l'URL publique avec neonctl functions get <slug> (le champ invocation_url, de la forme https://<branch_id>-<slug>.compute.c-1.us-east-2.aws.neon.tech). Gérez avec neonctl functions list|get|delete.
Quand neonctl checkout crée une nouvelle branche et qu'un neon.ts est présent, il applique la policy automatiquement — déployant la fonction sur la branche fraîche. Faire un checkout d'une branche existante ne redéploie pas ; exécutez neonctl deploy explicitement.
Environment variables
Neon injecte des chaînes de connexion branch-scoped et des URLs de service à l'exécution — vous ne déclarez pas celles-ci ou ne les passez pas au moment du déploiement :
| Variable | Notes |
|---|---|
DATABASE_URL |
Chaîne de connexion poolée. Utilisez pour la plupart des requêtes. Présent uniquement si la branche a Postgres. |
DATABASE_URL_UNPOOLED |
Connexion directe. Utilisez pour les migrations, LISTEN/NOTIFY, les transactions multi-round-trip. |
NEON_AUTH_BASE_URL |
Présent quand Neon Auth est activé sur la branche. |
NEON_DATA_API_URL |
Présent quand l'API Data est activée sur la branche. |
Les variables de stockage d'objet (AWS_*) et AI Gateway (OPENAI_*, NEON_AI_GATEWAY_*) sont aussi injectées quand ces services sont déclarés — voir les skills neon-object-storage et neon-ai-gateway.
Vos propres secrets sont par-déploiement. Définissez-les avec --env KEY=VALUE sur neonctl functions deploy (répétable ; --env KEY= supprime une clé, les clés non mentionnées se reportent), ou déclarez-les dans neon.ts sous l'env de la fonction (résolus au moment du déploiement, donc lisez depuis process.env pour éviter le hardcoding) :
functions: {
todos: {
name: "todo api",
source: "src/index.ts",
env: { OPENAI_API_KEY: process.env.OPENAI_API_KEY! },
},
}
Chargez un .env avant déploiement avec neonctl deploy --env .env.production. Tirez les variables gérées par Neon de la branche sur le disque pour le dev local avec neonctl env pull (link/checkout font ceci automatiquement ; passez --no-env-pull pour passer et utiliser neon-env run -- <cmd> pour l'injection à l'exécution). Limites : ≤1 000 variables, ≤64 KiB total, et le préfixe NEON_ est réservé.
Timeouts and runtime limits
Les fonctions sont long-running mais toujours serverless — ce sont un runtime request/response, pas un runner de travail background. Les limites dures :
- Temps au premier byte : 15 minutes. Votre gestionnaire doit commencer à renvoyer une réponse dans les 15 minutes de réception d'une requête. La plupart des gestionnaires terminent en secondes ; le plafond de 15 minutes existe pour que les charges de travail d'agent comme la génération d'image/vidéo aient de l'espace.
- Heartbeat : 15 minutes. Les connexions WebSocket/SSE ouvertes restent actives tant que les données s'écoulent. Le timeout ne se déclenche que quand une connexion devient silencieuse — envoyez au moins un byte tous les 15 minutes pour garder un stream silencieux actif.
waitUntil: 15 minutes. Le travail enregistré avecwaitUntilmaintient l'invocation active après l'envoi de la réponse, jusqu'à 15 minutes — pour le nettoyage comme les écritures d'analyse et les journaux d'audit, pas un runner de travail background. (waitUntildepuis@neondatabase/functions/v1est actuellement un stub pendant l'aperçu.)- Eviction au repos. Sans connexions actives, la plateforme arrête la fonction ; elle peut aussi évincer/redémarrer pour des raisons opérationnelles (les fonctions actives peuvent s'exécuter pendant des heures d'abord). Traitez l'éviction comme un redémarrage de processus — les clients WebSocket/SSE doivent se reconnecter. La plateforme envoie
SIGINTavant d'évincer, donc enregistrez un gestionnaire pour drainer proprement :
process.on("SIGINT", () => {
pool.end().then(() => process.exit(0));
});
- Runtime : Node.js 24, une requête à la fois par isolate (les requêtes supplémentaires mettent en queue, elles ne faill pas), mémoire fixée à 2 048 MiB pendant l'aperçu. Les slugs doivent matcher
^[a-z0-9]{1,20}$. L'état détenu au niveau du module est par-isolate et en mémoire uniquement — persistez tout ce qui doit survivre à l'éviction dans Postgres.
Availability
Neon Functions est une fonctionnalité en aperçu (early access) disponible uniquement sur les nouveaux projets dans la région us-east-2. Confirmez que le projet Neon de l'utilisateur est un nouveau projet dans us-east-2 ; elle ne peut pas être activée sur les projets existants. L'utilisation de Functions n'est pas facturée pendant la private preview. Si l'utilisateur n'a pas encore accès, pointez-le vers le sign-up beta privée : https://neon.com/blog/were-building-backends#access
Neon Documentation
La documentation Neon est la source de vérité et Functions évolue rapidement, donc vérifiez toujours contre les docs officiels. N'importe quelle page de doc peut être récupérée en markdown en ajoutant .md à l'URL ou en requêtant Accept: text/markdown. Trouvez la bonne page depuis l'index des docs (https://neon.com/docs/llms.txt) et les annonces du changelog.
Further reading
- https://neon.com/docs/compute/functions/overview.md
- https://neon.com/docs/compute/functions/get-started.md
- https://neon.com/docs/compute/functions/deploy.md
- https://neon.com/docs/compute/functions/environment-variables.md
- https://neon.com/docs/compute/functions/reference/neon-ts.md
- https://neon.com/docs/compute/functions/reference/runtime-limits.md
- https://neon.com/docs/compute/functions/preview-access.md