[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-neon-neon-functions":3,"mdc--1b0s4z-key":41,"related-org-neon-neon-functions":10829,"related-repo-neon-neon-functions":10993},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":12,"stars":30,"repoUrl":31,"updatedAt":32,"license":33,"forks":34,"topics":35,"repo":36,"sourceUrl":39,"mdContent":40},"neon-functions","deploy serverless functions on Neon","Long-running, serverless Node.js HTTP functions deployed onto your Neon branch, with DATABASE_URL injected automatically and compute that runs next to your data. Use when a user wants to host an API, an AI agent with long streaming responses, a WebSocket or server-sent-events (SSE) server, a webhook handler, a Discord bot, an MCP server, or any request\u002Fresponse workload that risks timing out on short, lambda-style serverless functions — and wants it to branch with their database. Triggers include \"serverless function\", \"deploy an API\", \"long-running function\", \"streaming agent\", \"SSE server\", \"WebSocket server\", \"webhook handler\", \"MCP server\", \"run code next to my database\", \"function that won't time out\", \"Neon Functions\", and \"Neon Compute\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},"neon","Neon","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fneon.png","neondatabase",[13,15,18,21,24,27],{"name":9,"slug":8,"type":14},"tag",{"name":16,"slug":17,"type":14},"Backend","backend",{"name":19,"slug":20,"type":14},"Node.js","node-js",{"name":22,"slug":23,"type":14},"API Development","api-development",{"name":25,"slug":26,"type":14},"Serverless","serverless",{"name":28,"slug":29,"type":14},"Edge Functions","edge-functions",81,"https:\u002F\u002Fgithub.com\u002Fneondatabase\u002Fagent-skills","2026-07-27T06:07:59.147675",null,12,[],{"repoUrl":31,"stars":30,"forks":34,"topics":37,"description":38},[],"Agent Skills for Neon Severless Postgres","https:\u002F\u002Fgithub.com\u002Fneondatabase\u002Fagent-skills\u002Ftree\u002FHEAD\u002Fskills\u002Fneon-functions","---\nname: neon-functions\ndescription: >-\n  Long-running, serverless Node.js HTTP functions deployed onto your Neon\n  branch, with DATABASE_URL injected automatically and compute that runs next\n  to your data. Use when a user wants to host an API, an AI agent with long\n  streaming responses, a WebSocket or server-sent-events (SSE) server, a\n  webhook handler, a Discord bot, an MCP server, or any request\u002Fresponse\n  workload that risks timing out on short, lambda-style serverless functions —\n  and wants it to branch with their database. Triggers include \"serverless\n  function\", \"deploy an API\", \"long-running function\", \"streaming agent\",\n  \"SSE server\", \"WebSocket server\", \"webhook handler\", \"MCP server\",\n  \"run code next to my database\", \"function that won't time out\",\n  \"Neon Functions\", and \"Neon Compute\".\nmetadata:\n  parent: neon\n---\n\n**FIRST**: Use the parent `neon` skill for a Neon platform overview, getting started with Neon, Neon development best practices, and more.\n\nIf the `neon` skill is not installed, fetch it from https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon\u002FSKILL.md or install it with:\n\n```bash\nnpx skills add neondatabase\u002Fagent-skills --skill neon\n```\n\n# Neon Functions\n\nThis is a public beta feature and only available in `us-east-2`.\n\nNeon Functions are long-running Node.js HTTP handlers deployed onto a Neon branch. Each function gets a public HTTPS URL, runs in the same region as your database, and — if the branch has Postgres — gets `DATABASE_URL` injected automatically. You deploy and manage them through the same Neon CLI, `neon.ts`, and API you already use.\n\nUse this skill to help the user define, run locally, deploy, and manage functions next to their database. Deliver a deployed function with its invocation URL, a working local `neon dev` loop, or a precise answer from the official Neon docs.\n\n## When to Use\n\nReach for Neon Functions when the workload is a request\u002Fresponse handler that benefits from staying alive and staying close to the data:\n\n- **Long-running request\u002Fresponse flows that outlast lambda-style limits.** Agents that make several LLM calls and tool invocations per request, or image\u002Fvideo generation, routinely blow past the ~10–60s execution caps and short streaming windows of traditional serverless functions. Neon Functions are long-running: the handler just needs to _start_ responding within 15 minutes, and an open stream stays alive as long as bytes keep flowing. That's enough headroom for real agent workloads.\n- **Stateful streaming without bolting on Redis.** Because a function stays alive across a request, it can host an SSE endpoint or a WebSocket server and hold the connection open in-process — no external state store (Redis, etc.) needed just to keep a stream coherent. Module-scope state (a `pg` pool, an in-memory counter) persists across requests on the same isolate.\n- **Compute that must sit next to Postgres.** The function runs in the same region as the branch's database, so there are no cross-region round trips on every query. `DATABASE_URL` is injected for you.\n- **A backend that branches with your data.** Each branch runs its own version of the function at its own URL, against its own isolated database (and storage, and gateway) state. Preview deployments, CI, and dev environments each get a self-contained backend — deploying to a child never affects the parent.\n- **Webhooks, bots, and post-response work.** Webhook handlers that fan out into multiple DB writes, Discord\u002FWebSocket bots, and fire-and-forget follow-ups via `waitUntil` (analytics, audit logs) all fit.\n\nIf the workload is a pure static site, a cron\u002Fbackground job that needs its own lifecycle and cancellation, or something that must run outside `us-east-2` today, this isn't the right tool yet (see [Timeouts and Runtime Limits](#timeouts-and-runtime-limits) and [Availability](#availability)).\n\n## What It Does\n\n- **Long-running & serverless** — Built for WebSocket servers (see [WebSocket Servers](#websocket-servers)), SSE endpoints (see [Server-Sent Events (SSE)](#server-sent-events-sse)), long agent HTTP streams, and APIs. Still scales to zero when idle.\n- **Web-standard handler** — A function is any default export with a `fetch(request)` method returning a `Response` (Workers\u002FWinterTC-compatible). A Hono app exports exactly that shape, so `export default app` just works. Runs on Node.js 24, so all Node APIs are available.\n- **Close to your database** — Runs in the branch's region; `DATABASE_URL` injected automatically when the branch has Postgres.\n- **Branchable** — Each branch runs its own function version at its own URL against its own isolated state.\n- **Same CLI\u002FAPI** — Deploy and manage via `neon`, `neon.ts`, or the Neon API.\n\n## Availability\n\nCheck this precondition before setting anything up: Neon Functions is a public beta feature available only on new projects in the `us-east-2` region. Confirm the user's Neon project is a new project in `us-east-2`; it can't be enabled on existing projects. Functions usage isn't billed during the public beta.\n\n## Architecture: Where Functions Fit\n\nNeon (Functions included) is **backend primitives, not full-stack app hosting**. Host your app on **Vercel** (or Netlify, or another frontend\u002Fapp host); Functions are the long-running, stateful slice of your backend that lives next to your data. They compose with that platform in two ways:\n\n- **Add a Function to a full-stack app.** Your Next.js \u002F TanStack Start app on Vercel (or Netlify) owns UI, auth (e.g. Neon Auth), and talks directly to Neon Postgres and Object Storage. When one workload outgrows the host's short serverless limits — a WebSocket or SSE server, or a long-running agent that would time out — move just that piece onto a Neon Function. (See [Functions as an Agent Backend](#functions-as-an-agent-backend-nextjs-and-similar-frameworks) for the client-direct pattern.)\n- **Run the whole backend control plane on Functions.** Especially when the frontend is **client-only** — TanStack Router, React Router in client mode, and similar SPAs hosted on Vercel or Netlify — the client calls Functions **directly**. Build REST APIs and request\u002Fresponse agents, host **MCP servers**, and run anything stateful or that belongs close to Postgres and Object Storage.\n\nEither way, secure a Function like any standalone REST API: verify a JWT or API key at the top of the handler (see the WARNING under [Functions as an Agent Backend](#functions-as-an-agent-backend-nextjs-and-similar-frameworks)). Because a Function is just your backend, you can **move pieces between your host and Neon** — relocate an agent or a stateful WebSocket server onto a Function when it needs more runtime, and back if needed.\n\n## Setup\n\nFunctions are declared in `neon.ts` (see the `neon` skill for the branch-first workflow and `neon.ts` basics). Add `@neon\u002Fconfig` and declare functions under `preview.functions`, keyed by **slug**:\n\n```typescript\n\u002F\u002F neon.ts\nimport { defineConfig } from \"@neon\u002Fconfig\u002Fv1\";\n\nexport default defineConfig({\n  preview: {\n    functions: {\n      todos: {\n        \u002F\u002F slug: ^[a-z0-9]{1,20}$ — lowercase letters\u002Fdigits, no hyphens\n        name: \"todo api\", \u002F\u002F display label only\n        source: \"src\u002Findex.ts\", \u002F\u002F entry file, relative to neon.ts\n      },\n    },\n  },\n});\n```\n\nThe slug is the function's permanent identity (it appears in the invocation URL and CLI commands) and can't be changed after the first deploy. Use `name` for a human-readable label.\n\nA minimal function — a Hono app that queries the branch's Postgres via the injected `DATABASE_URL`:\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport { Hono } from \"hono\";\nimport { drizzle } from \"drizzle-orm\u002Fnode-postgres\";\nimport { Pool } from \"pg\";\nimport { parseEnv } from \"@neon\u002Fenv\";\nimport config from \"..\u002Fneon\";\nimport { todos } from \".\u002Fdb\u002Fschema\";\n\nconst env = parseEnv(config);\nconst pool = new Pool({ connectionString: env.postgres.databaseUrl, max: 5 });\nconst db = drizzle(pool);\n\nconst app = new Hono();\napp.get(\"\u002F\", (c) => c.text(\"Neon + Hono + Drizzle\"));\napp.post(\"\u002Ftodos\", async (c) => {\n  const { text } = await c.req.json\u003C{ text: string }>();\n  const [row] = await db.insert(todos).values({ text }).returning();\n  return c.json(row, 201);\n});\napp.get(\"\u002Ftodos\", async (c) => c.json(await db.select().from(todos)));\n\nexport default app;\n```\n\nCreate the `pg` pool at module scope (reused across requests on the same isolate) and keep `max` small (e.g. 5), since each isolate keeps its own pool.\n\n`parseEnv(config)` requires _every_ variable the config implies. A function that only talks to Postgres over the pooled URL can scope it to just that key — `parseEnv` then validates and returns only what you asked for (the keys autocomplete from your `neon.ts`):\n\n```typescript\nconst { postgres } = parseEnv(config, [\"DATABASE_URL\"]); \u002F\u002F not the unpooled URL, auth, etc.\nconst pool = new Pool({ connectionString: postgres.databaseUrl, max: 5 });\n```\n\n## Develop Locally and Deploy\n\n```bash\nneon dev      # serves every function in neon.ts with hot reload; injects DATABASE_URL & friends\nneon deploy   # bundles with esbuild, uploads, and applies neon.ts to the linked branch\n```\n\nTo deploy a single function without `neon.ts`: `neon functions deploy \u003Cslug> --src src\u002Findex.ts` (`--src` takes either the entry file or a directory containing `index.ts`, `index.mjs`, or `index.js`). Retrieve the public URL with `neon functions get \u003Cslug>` (the `invocation_url` field, of the form `https:\u002F\u002F\u003Cbranch_id>-\u003Cslug>.compute.c-1.us-east-2.aws.neon.tech`). Manage with `neon functions list|get|delete`.\n\nWhen `neon checkout` _creates_ a new branch and a `neon.ts` is present, it applies the policy automatically — deploying the function to the fresh branch. Checking out an existing branch does not re-deploy; run `neon deploy` explicitly.\n\n## Neon Infrastructure as Code (`neon.ts`)\n\nThe `preview.functions` block from [Setup](#setup) is part of `neon.ts`, Neon's infrastructure-as-code file — one TypeScript file declares every function (its `source`, display `name`, and `env`) alongside any other branch services, in version control (see the `neon` skill for the full reference). Treat it like Terraform for your branch:\n\n```bash\nneon config status   # print the branch's live config (deployed functions)\nneon config plan     # dry-run diff of what apply would change\nneon config apply    # bundle + deploy the declared functions  (neon deploy is an alias)\n```\n\nFunctions are **branch-scoped**: each branch runs its own deployment at its own URL. When a `neon.ts` is present, `neon checkout` applies the policy as it _creates_ a branch, so a fresh preview\u002FCI branch comes up with the function already deployed. Checking out an _existing_ branch doesn't redeploy — run `neon deploy` to apply changes.\n\nPer-branch deploy tuning (e.g. `runtime`) lives in the `branch` closure, keyed by slug, so it can vary by branch without changing which functions exist:\n\n```typescript\nexport default defineConfig({\n  preview: {\n    functions: { todos: { name: \"todo api\", source: \"src\u002Findex.ts\" } },\n  },\n  branch: (branch) => ({\n    preview: { functions: { todos: { runtime: \"nodejs24\" } } },\n  }),\n});\n```\n\n## Environment Variables\n\nNeon injects branch-scoped connection strings and service URLs at runtime — you don't declare these or pass them at deploy time:\n\n| Variable                | Notes                                                                                    |\n| ----------------------- | ---------------------------------------------------------------------------------------- |\n| `NEON_BRANCH`           | The branch **name** (e.g. `main`, `preview\u002Ffoo`). Injected on every branch, including the default. |\n| `DATABASE_URL`          | Pooled connection string. Use for most queries. Present only if the branch has Postgres. |\n| `DATABASE_URL_UNPOOLED` | Direct connection. Use for migrations, `LISTEN`\u002F`NOTIFY`, multi-round-trip transactions. |\n| `NEON_AUTH_BASE_URL`    | Present when Neon Auth is enabled on the branch.                                         |\n| `NEON_DATA_API_URL`     | Present when the Data API is enabled on the branch.                                      |\n\nObject storage (`AWS_*`) and AI Gateway (`NEON_AI_GATEWAY_*`) vars are also injected when those services are declared — see the `neon-object-storage` and `neon-ai-gateway` skills.\n\n`neon env pull` \u002F `neon-env run` \u002F `neon dev` emit `NEON_BRANCH` (and the connection strings) into your local dev environment too, so local runs mirror the deployed runtime.\n\n**Your own secrets** are per-deployment. Set them with `--env KEY=VALUE` on `neon functions deploy` (repeatable; `--env KEY=` deletes a key, unmentioned keys carry over), or declare them in `neon.ts` under the function's `env` (resolved at deploy time, so read from `process.env` to avoid hardcoding):\n\n```typescript\nfunctions: {\n  todos: {\n    name: \"todo api\",\n    source: \"src\u002Findex.ts\",\n    env: { RESEND_API_KEY: process.env.RESEND_API_KEY! },\n  },\n}\n```\n\nLoad a `.env` before deploy with `neon deploy --env .env.production`. Pull the branch's Neon-managed vars onto disk for local dev with `neon env pull` (`link`\u002F`checkout` do this automatically; pass `--no-env-pull` to skip and use `neon-env run -- \u003Ccmd>` for runtime injection). Limits: ≤1,000 vars, ≤64 KiB total, and the `NEON_` prefix is reserved.\n\n## Connecting to Postgres\n\nWhen the branch has Postgres, Neon **injects the connection strings at runtime** — you don't declare them, pass them at deploy time, or hardcode anything. The two you'll use:\n\n- `DATABASE_URL` — **pooled** connection string (routed through Neon's connection pooler). Use it for normal request\u002Fresponse query traffic. Kept un-prefixed because every Postgres ORM (Drizzle, Prisma, Knex, …) reads `DATABASE_URL` by default.\n- `DATABASE_URL_UNPOOLED` — **direct** connection string to the same database. Use it for migrations, `LISTEN`\u002F`NOTIFY`, and long multi-statement transactions.\n\n**Use Drizzle (or another ORM) on top of node-postgres (`pg`)** for queries and schema management — not Neon's serverless driver. Functions are long-running and reuse an isolate across many requests, so a persistent `pg` pool is the right fit; the serverless driver's HTTP transport is meant for fully isolated, lambda-style runtimes.\n\nCreate the connection pool **once at module scope** and reuse it across requests — don't open a connection per request:\n\n```typescript\nimport { drizzle } from \"drizzle-orm\u002Fnode-postgres\";\nimport { Pool } from \"pg\";\n\n\u002F\u002F Created once per isolate; reused by every request that isolate handles.\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 5 });\nconst db = drizzle(pool);\n```\n\n**Pooling is recommended because an isolate is reused across many requests** (and several requests can be in flight on the same isolate at once — see [Timeouts and Runtime Limits](#timeouts-and-runtime-limits)). A module-scope pool is opened once on cold start and then shared by every subsequent request that isolate serves, so you amortize connection setup instead of paying it on every request and you avoid exhausting Postgres connections under load.\n\nKeep `max` small (e.g. `5`): each isolate keeps its own pool, so total connections to Postgres scale with the number of live isolates. You don't need to close the pool on shutdown — when the runtime evicts an isolate it sends `SIGINT`\u002F`SIGTERM`, and Neon's pooler reclaims those connections for you, so an explicit drain handler is redundant.\n\n> Reading `process.env.DATABASE_URL` directly works everywhere. The function in [Setup](#setup) instead uses `@neon\u002Fenv`'s `parseEnv(config)` to read the same value in a typed, validated way — either is fine.\n\n## Timeouts and Runtime Limits\n\nFunctions are long-running but **still serverless** — they are a request\u002Fresponse runtime, not a background job runner. The hard limits:\n\n- **Time to first byte: 15 minutes.** Your handler must _begin_ returning a response within 15 minutes of receiving a request. Most handlers finish in seconds; the 15-minute ceiling exists so agent workloads like image\u002Fvideo generation have room.\n- **Heartbeat: 15 minutes.** Open WebSocket\u002FSSE connections stay alive as long as data flows. The timeout only fires when a connection goes silent — send at least one byte every 15 minutes to keep a quiet stream alive.\n- **`waitUntil`: 15 minutes.** Work registered with `waitUntil` keeps the invocation alive after the response is sent, up to 15 minutes — for cleanup like analytics writes and audit logs, **not** a background job runner. (`waitUntil` from `@neon\u002Ffunctions` is currently a stub during the preview.)\n- **Idle eviction.** With no active connections the platform shuts the function down; it may also evict\u002Frestart for operational reasons — e.g. maintenance, or moving the function to a different compute node (active functions can run for hours first). Treat eviction like a process restart — WebSocket\u002FSSE clients must reconnect. The platform sends `SIGINT` before evicting, so a `process.on(\"SIGINT\", ...)` handler lets you detect that the function is about to be evicted and run any last-minute cleanup. You don't need one just to close Postgres connections — Neon's pooler reclaims those on its own.\n- **Runtime:** Node.js 24, memory fixed at 2048 MiB during the preview. Slugs must match `^[a-z0-9]{1,20}$`. **An isolate is reused across many requests** — multiple requests can be in flight on the same isolate at once (interleaved on Node's single-threaded event loop), and under load the runtime runs several isolates in parallel, each with its own copy of module state. State held in module scope is therefore per-isolate (shared by every request that isolate handles) and in-memory only — persist anything that must survive eviction in Postgres. This reuse is exactly why you create a connection pool once at module scope rather than per request (see [Connecting to Postgres](#connecting-to-postgres)).\n\n## Functions as an Agent Backend (Next.js and Similar Frameworks)\n\nA Neon Function is a great home for an AI agent precisely because it **doesn't time out** the way lambda-style serverless does (15-minute budget, see [Timeouts and Runtime Limits](#timeouts-and-runtime-limits)). But that advantage disappears the moment you **proxy the agent stream through your web app's backend** — a Next.js route handler, Remix\u002FSvelteKit\u002FNuxt action, etc. hosted on Vercel, Netlify, Cloudflare, and the like. Those platforms cap serverless\u002Fedge execution at short windows (often ~10–60s, sometimes up to ~300s), so a long agent or image\u002Fvideo generation stream gets cut off mid-response even though the Neon Function would happily keep going.\n\n**Building the agent itself.** The [Vercel AI SDK](https:\u002F\u002Fai-sdk.dev) and [Mastra](https:\u002F\u002Fmastra.ai) are the recommended ways to build the agent — point either at the Neon AI Gateway (see the `neon-ai-gateway` skill) for one credential across every model, with no extra provider keys. For a complete AI SDK agent running as a Function (streaming `toUIMessageStreamResponse`, multi-step tool calling next to Postgres, and persisting generated images to Object Storage), see [references\u002Fai-sdk.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fai-sdk.md); for the Mastra equivalent with built-in tracing, see [references\u002Fmastra-studio.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fmastra-studio.md).\n\n**The fix: call the function directly from the client.** Don't route the long request through your app server.\n\n```\nBrowser ──(Authorization: Bearer \u003CJWT>)──▶  Neon Function (agent)   ✅ no host timeout\nBrowser ──▶ your app backend ──▶ Neon Function                       ❌ host cuts the stream\n```\n\n- Mint a **short-lived JWT** on your app backend (e.g. better-auth's `jwt` plugin, NextAuth, or your own signer) — that call is fast and well within host limits.\n- Hand the token to the client and have it call the Neon Function **directly** (cross-origin), e.g. with the Vercel AI SDK: `new DefaultChatTransport({ api: NEON_FUNCTION_URL, fetch })` where `fetch` attaches `Authorization: Bearer \u003Ctoken>`. Your app server is never in the path of the long stream.\n- Add **CORS** so the browser can reach it (handle `OPTIONS`, set `Access-Control-Allow-Origin`\u002F`-Headers`).\n\n> [!WARNING]\n> A Neon Function has a **public HTTPS URL — it is reachable by anyone.** A direct client→function call means there is no app backend in front of it to gate access, so **you must authenticate the function yourself.** Verify a JWT (e.g. against your app's JWKS), check a shared secret \u002F API key, or validate a session token at the top of the handler and reject anything else. Never deploy an unauthenticated agent.\n\n```typescript\n\u002F\u002F src\u002Findex.ts — verify the caller before doing any work\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\n\nconst jwks = createRemoteJWKSet(new URL(`${process.env.AUTH_BASE_URL}\u002Fapi\u002Fauth\u002Fjwks`));\n\nexport default {\n  async fetch(request: Request) {\n    if (request.method === \"OPTIONS\") return new Response(null, { status: 204, headers: cors(request) });\n\n    const auth = request.headers.get(\"authorization\");\n    if (!auth?.toLowerCase().startsWith(\"bearer \")) {\n      return new Response(\"Unauthorized\", { status: 401, headers: cors(request) });\n    }\n    try {\n      const { payload } = await jwtVerify(auth.slice(7), jwks, {\n        issuer: process.env.AUTH_BASE_URL,\n        audience: process.env.AUTH_BASE_URL,\n      });\n      const userId = payload.sub; \u002F\u002F scope the agent to this user\n      \u002F\u002F ... run the agent, return result.toUIMessageStreamResponse({ headers: cors(request) })\n    } catch {\n      return new Response(\"Unauthorized\", { status: 401, headers: cors(request) });\n    }\n  },\n};\n```\n\nPass the JWKS\u002Fissuer URL to the function via its `env` (see [Environment Variables](#environment-variables)). Persist anything you need to keep (generated images, history) in Postgres — module state doesn't survive eviction.\n\n## WebSocket Servers\n\nA WebSocket server is the canonical Functions workload: a long-running handler holds connections open in-process, with no external state store needed to keep a stream coherent. Because a function is a real Node.js process (not a lambda), the WebSocket handshake works the way it does in any Node server — the [`ws`](https:\u002F\u002Fgithub.com\u002Fwebsockets\u002Fws) library upgrades the socket, and the connection stays alive as long as bytes flow (15-minute heartbeat, see [Timeouts](#timeouts-and-runtime-limits)).\n\n**The return signature is the whole trick.** A function's default export is normally `{ fetch }`. To also accept WebSockets, export an `upgrade` method alongside it — the runtime routes plain HTTP to `fetch` and the WebSocket handshake to `upgrade`:\n\n```typescript\nexport default {\n  fetch(request: Request): Response | Promise\u003CResponse> { \u002F* HTTP *\u002F },\n  async upgrade(req: IncomingMessage, socket: Duplex, head: Buffer) { \u002F* WS handshake *\u002F },\n};\n```\n\n**Simple example** — raw `ws`, no framework, with auth. Browsers can't set headers on a WebSocket, so authenticate with a `?token=` query param (verify it the same way as the [agent backend](#functions-as-an-agent-backend-nextjs-and-similar-frameworks): `jwtVerify` against your JWKS) before accepting the connection:\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport { WebSocketServer, type WebSocket } from \"ws\";\n\nconst clients = new Set\u003CWebSocket>();\nconst wss = new WebSocketServer({ noServer: true });\n\nexport default {\n  \u002F\u002F Plain HTTP (health checks, REST) is handled by fetch.\n  fetch: () => new Response(\"WebSocket endpoint — connect with ?token=\u003Cjwt>\"),\n\n  \u002F\u002F The runtime hands the WebSocket handshake to upgrade().\n  async upgrade(req: IncomingMessage, socket: Duplex, head: Buffer) {\n    const url = new URL(req.url ?? \"\u002F\", \"http:\u002F\u002Flocalhost\");\n    const identity = await verifyToken(url.searchParams.get(\"token\")); \u002F\u002F reject if invalid\n    if (!identity) {\n      socket.write(\"HTTP\u002F1.1 401 Unauthorized\\r\\n\\r\\n\");\n      socket.destroy();\n      return;\n    }\n    wss.handleUpgrade(req, socket, head, (ws) => {\n      clients.add(ws);\n      ws.on(\"close\", () => clients.delete(ws));\n      ws.on(\"message\", (data) => persist(data.toString())); \u002F\u002F persist; fan out to every isolate — see below\n    });\n  },\n};\n```\n\n**Hono variant.** If you only need Hono for the HTTP side and are happy driving `ws` yourself, just swap `fetch` in the simple example for `app.fetch` and keep the raw `upgrade` — Hono serves routing\u002Fmiddleware, `ws` serves the socket.\n\nTo instead declare WebSocket routes _inside_ the Hono app — `app.get(\"\u002Fws\", upgradeWebSocket(...))` with the standard `onOpen`\u002F`onMessage`\u002F`onClose` lifecycle — you need an adapter that bridges Hono's `upgradeWebSocket()` helper to Neon's `upgrade(req, socket, head)`. Hono ships adapters for Cloudflare\u002FDeno\u002FBun\u002FNode, but **none for Neon**, and the Node one (`@hono\u002Fnode-ws`) is deprecated and assumes it owns the HTTP server. [references\u002Fhono-websockets.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fhono-websockets.md) has a small self-contained `createNeonWebSocket(app)` adapter to copy in — it depends only on `hono` and `ws` (no deprecated package; adapted from `@hono\u002Fnode-ws`, MIT) and returns a ready-to-export `{ fetch, upgrade }` handler. Usage is idiomatic Hono, and because the handshake routes through `app.request`, **auth is just normal route middleware**:\n\n```typescript\n\u002F\u002F src\u002Findex.ts\nimport { Hono } from \"hono\";\nimport { createNeonWebSocket } from \".\u002Fhono-ws\";\n\nconst app = new Hono();\nconst { upgradeWebSocket, handler } = createNeonWebSocket(app);\n\napp.get(\n  \"\u002Fws\",\n  async (c, next) => {\n    if (!(await verifyToken(c.req.query(\"token\")))) return c.text(\"Unauthorized\", 401);\n    await next();\n  },\n  upgradeWebSocket(() => ({\n    onOpen: (_evt, ws) => ws.send(\"welcome\"),\n    onMessage: (evt, ws) => ws.send(`echo: ${evt.data}`),\n    onClose: () => console.log(\"disconnected\"),\n  })),\n);\n\nexport default handler; \u002F\u002F Neon's { fetch, upgrade } contract\n```\n\n> Don't put header-modifying middleware (e.g. CORS) on an `upgradeWebSocket` route — the helper rewrites headers internally and will throw. The [sync](#keeping-clients-in-sync-across-isolates-do-not-skip-this) and [reconnect](#client-must-reconnect) guidance below applies unchanged.\n\n### Heartbeat (keep the socket alive)\n\nA connection stays open **only while bytes flow**: Neon evicts a silent stream after 15 minutes ([Timeouts and Runtime Limits](#timeouts-and-runtime-limits)), and intermediary proxies \u002F load balancers are usually far stricter (often tens of seconds). Don't rely on the app being chatty enough — send a periodic ping from the server so the socket never goes quiet. `ws.ping()` sends a WebSocket ping frame and the browser answers with a pong automatically, so there's no client code to write:\n\n```typescript\nconst HEARTBEAT_MS = 25_000; \u002F\u002F comfortably under proxy idle timeouts\n\nconst beat = setInterval(() => {\n  for (const ws of clients) if (ws.readyState === ws.OPEN) ws.ping();\n}, HEARTBEAT_MS);\nbeat.unref?.();\n```\n\n(With the Hono `upgradeWebSocket` helper you don't hold the raw socket, so send an application-level keepalive instead — e.g. `ws.send(\"ping\")` on the same interval, ignored by the client.)\n\n### Keeping clients in sync across isolates (do not skip this)\n\nUnder load the runtime runs **several isolates in parallel, each with its own copy of module state** — so each isolate has its own `clients` set. Broadcasting only to that local set means a client on isolate A never sees an event produced on isolate B, and the feed silently fractures. It's easy to miss: `neon dev` runs a single process (one isolate), so in-process broadcast always _looks_ fine locally but breaks in production, where concurrent connections spread across many isolates.\n\nModule state doesn't survive eviction anyway, so **Postgres is the shared source of truth**. Pick a fan-out strategy. In every snippet below, `pool` is a pooled `pg` client and `clients` is this isolate's `Set` of live connections.\n\n**1. Poll Postgres — the default, and the only option that keeps Scale to Zero.** Each isolate re-reads the shared state (or rows past a cursor) on a short interval and pushes changes to its own clients. One query per isolate per tick (not per client), and none when the isolate has no clients — so an idle compute still suspends.\n\n```typescript\nlet lastId = 0;\nconst poller = setInterval(async () => {\n  if (clients.size === 0) return; \u002F\u002F no clients here → no query → compute can scale to zero\n  const { rows } = await pool.query(\n    \"SELECT id, payload FROM events WHERE id > $1 ORDER BY id\",\n    [lastId],\n  );\n  for (const { id, payload } of rows) {\n    lastId = id;\n    for (const ws of clients) if (ws.readyState === ws.OPEN) ws.send(payload);\n  }\n}, 1000);\npoller.unref?.();\n```\n\n- **Latency:** up to the interval (~1s) — fine for counters, chat, and dashboards.\n- **Scaling:** database load grows with the number of live isolates, not clients. Keep the cursor on an indexed `serial`\u002F`bigserial` PK and the interval sane.\n- **Scale to Zero:** ✅ preserved — polling stops when no clients are connected, so the compute suspends on its normal timer.\n\n**2. `LISTEN`\u002F`NOTIFY` — lowest latency, but requires disabling Scale to Zero.** Each isolate `LISTEN`s on a channel over a dedicated **unpooled** connection; broadcasting is `NOTIFY`, so every isolate (including the sender's) re-pushes to its sockets. Near-instant — but the listener holds an idle connection that **does not count as active**, so [Scale to Zero](https:\u002F\u002Fneon.com\u002Fdocs\u002Fintroduction\u002Fscale-to-zero) suspends the compute and drops it, silently killing the feed. Only use it on an **always-on** compute (Scale to Zero disabled — a paid-plan setting).\n\n```typescript\nimport { Pool, Client } from \"pg\";\n\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 5 });\nconst CHANNEL = \"chat_events\";\n\n\u002F\u002F One dedicated DIRECT connection per isolate, just to receive events.\n\u002F\u002F Use DATABASE_URL_UNPOOLED — LISTEN needs a real session, not a pooled one.\nconst listener = new Client({ connectionString: process.env.DATABASE_URL_UNPOOLED });\nlistener.connect().then(() => listener.query(`LISTEN ${CHANNEL}`));\nlistener.on(\"notification\", (msg) => {\n  if (!msg.payload) return;\n  for (const ws of clients) if (ws.readyState === ws.OPEN) ws.send(msg.payload);\n});\n\n\u002F\u002F Broadcast by NOTIFYing through the pool — every isolate's listener fires.\nfunction broadcast(event: unknown) {\n  return pool.query(\"SELECT pg_notify($1, $2)\", [CHANNEL, JSON.stringify(event)]);\n}\n```\n\n**3. External pub\u002Fsub (e.g. [Upstash](https:\u002F\u002Fupstash.com) Redis) — best at scale.** For high fan-out, sub-second latency at large connection counts, or multi-region, publish\u002Fsubscribe through a dedicated broker. Highest throughput, and it doesn't touch Postgres or block Scale to Zero — at the cost of another service to run.\n\n**Rule of thumb:** start with **polling** (works with Scale to Zero, no extra infra); switch to `LISTEN`\u002F`NOTIFY` only on always-on compute that needs sub-second latency; move to Redis when fan-out outgrows Postgres.\n\n### Client must reconnect\n\nIdle functions are evicted (and isolates restart for operational reasons), so a client's socket **will** drop — treat reconnection as normal, not exceptional. Reconnect with exponential backoff, capped, and **re-mint a fresh token on every attempt** (tokens are short-lived, so a stale one fails the `upgrade` auth check):\n\n```typescript\nlet closed = false, retry = 0, timer: ReturnType\u003Ctypeof setTimeout>;\n\nasync function connect() {\n  if (closed) return;\n  const token = await getToken(); \u002F\u002F re-mint each attempt; short-lived\n  const ws = new WebSocket(`${WS_URL}?token=${encodeURIComponent(token)}`);\n  ws.onopen = () => { retry = 0; };          \u002F\u002F reset backoff on success\n  ws.onmessage = (e) => { \u002F* apply the event *\u002F };\n  ws.onclose = () => {\n    if (!closed) timer = setTimeout(connect, Math.min(1000 * 2 ** retry++, 15000));\n  };\n  ws.onerror = () => ws.close();             \u002F\u002F let onclose drive the retry\n}\nconnect();\n```\n\nTogether — Hono `fetch` + `ws` `upgrade`, JWT auth over `?token=`, cross-isolate fan-out, and client backoff — these compose into a complete realtime chat backend on a single function.\n\n## Server-Sent Events (SSE)\n\nWhen you only need **server → client** streaming (live counters, notifications, progress, token streams), SSE is simpler than a WebSocket and needs no `upgrade` method or extra library: a plain `fetch` handler returns a `Response` whose body is a `ReadableStream` with `Content-Type: text\u002Fevent-stream`, and the runtime holds it open as long as bytes flow. The browser consumes it with `EventSource`, which **reconnects on its own** — so there's no client backoff to write.\n\n```typescript\n\u002F\u002F src\u002Findex.ts — minimal SSE endpoint\nconst encoder = new TextEncoder();\nexport default {\n  fetch: () =>\n    new Response(\n      new ReadableStream\u003CUint8Array>({\n        start(controller) {\n          controller.enqueue(encoder.encode(\"data: hello\\n\\n\"));\n          const t = setInterval(() => controller.enqueue(encoder.encode(\": ping\\n\\n\")), 25_000);\n          return () => clearInterval(t); \u002F\u002F fires when the client disconnects\n        },\n      }),\n      { headers: { \"Content-Type\": \"text\u002Fevent-stream\", \"Cache-Control\": \"no-cache, no-transform\" } },\n    ),\n};\n```\n\nThe same rules as WebSockets apply. **Heartbeat:** a stream stays open only while bytes flow — Neon's window is 15 minutes ([Timeouts and Runtime Limits](#timeouts-and-runtime-limits)) but proxies are usually far stricter, so emit a `: ping\\n\\n` comment every ~25–30s (shown above) to keep idle streams from being dropped. Keep state in Postgres, and fan out across isolates using one of the [sync strategies](#keeping-clients-in-sync-across-isolates-do-not-skip-this) (hold a `Set` of stream controllers and `enqueue` to each). `EventSource` is GET-only and can't set headers, so authenticate with a `?token=` query param or cookie, exactly like the WebSocket case. [references\u002Fsse.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fsse.md) has the full pattern — Hono variant, cross-isolate fan-out, wire format, client, and caveats.\n\n## MCP Servers\n\nAn [MCP](https:\u002F\u002Fmodelcontextprotocol.io) server is a natural Functions workload: a long-running HTTP handler that exposes tools to AI clients (Cursor, Claude, ChatGPT, agents), with those tools reading and writing the branch's Postgres right next to the compute. MCP's **streamable HTTP transport** is a plain `POST`\u002F`GET` on a single endpoint (conventionally `\u002Fmcp`), so it maps onto a function's `fetch` handler with no `upgrade` method or extra protocol.\n\nThe simplest host is a Hono app using the official [`@modelcontextprotocol\u002Fsdk`](https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Ftypescript-sdk) plus [`@hono\u002Fmcp`](https:\u002F\u002Fgithub.com\u002Fhonojs\u002Fmiddleware\u002Ftree\u002Fmain\u002Fpackages\u002Fmcp), which bridges the transport to a route. Build the server, register its tools, and create the transport once at module scope, then hand every `\u002Fmcp` request to it:\n\n```typescript\nconst transport = new StreamableHTTPTransport();\napp.all(\"\u002Fmcp\", async (c) => {\n  if (!mcpServer.isConnected()) await mcpServer.connect(transport);\n  return transport.handleRequest(c);\n});\n```\n\nBecause the function's URL is public, **authenticate before connecting the transport** — [Better Auth](https:\u002F\u002Fbetter-auth.com) covers both OAuth (its MCP plugin makes your app the authorization server so third-party clients self-authorize per the MCP spec) and a simpler API-key \u002F session-JWT check for your own callers. [references\u002Fmcp.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fmcp.md) has the full pattern — server with Postgres-backed tools via Drizzle, both Better Auth auth options, and testing with `mcporter` \u002F `add-mcp`.\n\n## Integrations and Observability\n\nA function is a long-lived Node.js process running a web-standard request\u002Fresponse handler, so standard Node integration SDKs work unchanged. Initialize them once at module load, gated on an env var so local dev and unconfigured branches stay a no-op, and pass secrets via `--env` or `neon.ts` `env`.\n\n- **Sentry** — error monitoring across the HTTP framework, the function runtime, and an agent's own caught\u002Ffallback failures (the long-running case Functions target): see [references\u002Fsentry.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fsentry.md).\n- **Mastra Studio (Mastra Cloud)** — run a Mastra agent on a function and ship its traces to a Studio project for observability: see [references\u002Fmastra-studio.md](https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fmastra-studio.md).\n\n## Neon Documentation\n\nThe Neon documentation is the source of truth and Functions is evolving rapidly, so always verify against the official docs. Any doc page can be fetched as markdown by appending `.md` to the URL or by requesting `Accept: text\u002Fmarkdown`. Find the right page from the docs index (https:\u002F\u002Fneon.com\u002Fdocs\u002Fllms.txt) and the changelog announcements.\n\n## Further Reading\n\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Foverview.md\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fget-started.md\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fdeploy.md\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fenvironment-variables.md\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Freference\u002Fneon-ts.md\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Freference\u002Fruntime-limits.md\n- https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fpreview-access.md\n",{"data":42,"body":44},{"name":4,"description":6,"metadata":43},{"parent":8},{"type":45,"children":46},"root",[47,69,91,140,146,159,180,193,200,205,291,319,325,439,444,463,469,488,540,558,564,613,899,912,923,1932,1952,1985,2140,2146,2187,2268,2303,2315,2371,2442,2488,2509,2786,2792,2797,2945,2981,3013,3069,3235,3301,3307,3319,3375,3398,3410,3624,3640,3675,3712,3717,3729,3859,3865,3890,3949,3959,3969,4061,4088,5038,5057,5062,5086,5125,5305,5344,6352,6398,6529,7252,7283,7290,7316,7540,7560,7566,7600,7642,7652,8104,8152,8219,8948,8967,8997,9003,9029,9609,9641,9646,9710,10213,10283,10289,10347,10385,10605,10648,10654,10679,10716,10722,10751,10757,10823],{"type":48,"tag":49,"props":50,"children":51},"element","p",{},[52,59,61,67],{"type":48,"tag":53,"props":54,"children":55},"strong",{},[56],{"type":57,"value":58},"text","FIRST",{"type":57,"value":60},": Use the parent ",{"type":48,"tag":62,"props":63,"children":65},"code",{"className":64},[],[66],{"type":57,"value":8},{"type":57,"value":68}," skill for a Neon platform overview, getting started with Neon, Neon development best practices, and more.",{"type":48,"tag":49,"props":70,"children":71},{},[72,74,79,81,89],{"type":57,"value":73},"If the ",{"type":48,"tag":62,"props":75,"children":77},{"className":76},[],[78],{"type":57,"value":8},{"type":57,"value":80}," skill is not installed, fetch it from ",{"type":48,"tag":82,"props":83,"children":87},"a",{"href":84,"rel":85},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon\u002FSKILL.md",[86],"nofollow",[88],{"type":57,"value":84},{"type":57,"value":90}," or install it with:",{"type":48,"tag":92,"props":93,"children":98},"pre",{"className":94,"code":95,"language":96,"meta":97,"style":97},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","npx skills add neondatabase\u002Fagent-skills --skill neon\n","bash","",[99],{"type":48,"tag":62,"props":100,"children":101},{"__ignoreMap":97},[102],{"type":48,"tag":103,"props":104,"children":107},"span",{"class":105,"line":106},"line",1,[108,114,120,125,130,135],{"type":48,"tag":103,"props":109,"children":111},{"style":110},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[112],{"type":57,"value":113},"npx",{"type":48,"tag":103,"props":115,"children":117},{"style":116},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[118],{"type":57,"value":119}," skills",{"type":48,"tag":103,"props":121,"children":122},{"style":116},[123],{"type":57,"value":124}," add",{"type":48,"tag":103,"props":126,"children":127},{"style":116},[128],{"type":57,"value":129}," neondatabase\u002Fagent-skills",{"type":48,"tag":103,"props":131,"children":132},{"style":116},[133],{"type":57,"value":134}," --skill",{"type":48,"tag":103,"props":136,"children":137},{"style":116},[138],{"type":57,"value":139}," neon\n",{"type":48,"tag":141,"props":142,"children":143},"h1",{"id":4},[144],{"type":57,"value":145},"Neon Functions",{"type":48,"tag":49,"props":147,"children":148},{},[149,151,157],{"type":57,"value":150},"This is a public beta feature and only available in ",{"type":48,"tag":62,"props":152,"children":154},{"className":153},[],[155],{"type":57,"value":156},"us-east-2",{"type":57,"value":158},".",{"type":48,"tag":49,"props":160,"children":161},{},[162,164,170,172,178],{"type":57,"value":163},"Neon Functions are long-running Node.js HTTP handlers deployed onto a Neon branch. Each function gets a public HTTPS URL, runs in the same region as your database, and — if the branch has Postgres — gets ",{"type":48,"tag":62,"props":165,"children":167},{"className":166},[],[168],{"type":57,"value":169},"DATABASE_URL",{"type":57,"value":171}," injected automatically. You deploy and manage them through the same Neon CLI, ",{"type":48,"tag":62,"props":173,"children":175},{"className":174},[],[176],{"type":57,"value":177},"neon.ts",{"type":57,"value":179},", and API you already use.",{"type":48,"tag":49,"props":181,"children":182},{},[183,185,191],{"type":57,"value":184},"Use this skill to help the user define, run locally, deploy, and manage functions next to their database. Deliver a deployed function with its invocation URL, a working local ",{"type":48,"tag":62,"props":186,"children":188},{"className":187},[],[189],{"type":57,"value":190},"neon dev",{"type":57,"value":192}," loop, or a precise answer from the official Neon docs.",{"type":48,"tag":194,"props":195,"children":197},"h2",{"id":196},"when-to-use",[198],{"type":57,"value":199},"When to Use",{"type":48,"tag":49,"props":201,"children":202},{},[203],{"type":57,"value":204},"Reach for Neon Functions when the workload is a request\u002Fresponse handler that benefits from staying alive and staying close to the data:",{"type":48,"tag":206,"props":207,"children":208},"ul",{},[209,228,246,263,273],{"type":48,"tag":210,"props":211,"children":212},"li",{},[213,218,220,226],{"type":48,"tag":53,"props":214,"children":215},{},[216],{"type":57,"value":217},"Long-running request\u002Fresponse flows that outlast lambda-style limits.",{"type":57,"value":219}," Agents that make several LLM calls and tool invocations per request, or image\u002Fvideo generation, routinely blow past the ~10–60s execution caps and short streaming windows of traditional serverless functions. Neon Functions are long-running: the handler just needs to ",{"type":48,"tag":221,"props":222,"children":223},"em",{},[224],{"type":57,"value":225},"start",{"type":57,"value":227}," responding within 15 minutes, and an open stream stays alive as long as bytes keep flowing. That's enough headroom for real agent workloads.",{"type":48,"tag":210,"props":229,"children":230},{},[231,236,238,244],{"type":48,"tag":53,"props":232,"children":233},{},[234],{"type":57,"value":235},"Stateful streaming without bolting on Redis.",{"type":57,"value":237}," Because a function stays alive across a request, it can host an SSE endpoint or a WebSocket server and hold the connection open in-process — no external state store (Redis, etc.) needed just to keep a stream coherent. Module-scope state (a ",{"type":48,"tag":62,"props":239,"children":241},{"className":240},[],[242],{"type":57,"value":243},"pg",{"type":57,"value":245}," pool, an in-memory counter) persists across requests on the same isolate.",{"type":48,"tag":210,"props":247,"children":248},{},[249,254,256,261],{"type":48,"tag":53,"props":250,"children":251},{},[252],{"type":57,"value":253},"Compute that must sit next to Postgres.",{"type":57,"value":255}," The function runs in the same region as the branch's database, so there are no cross-region round trips on every query. ",{"type":48,"tag":62,"props":257,"children":259},{"className":258},[],[260],{"type":57,"value":169},{"type":57,"value":262}," is injected for you.",{"type":48,"tag":210,"props":264,"children":265},{},[266,271],{"type":48,"tag":53,"props":267,"children":268},{},[269],{"type":57,"value":270},"A backend that branches with your data.",{"type":57,"value":272}," Each branch runs its own version of the function at its own URL, against its own isolated database (and storage, and gateway) state. Preview deployments, CI, and dev environments each get a self-contained backend — deploying to a child never affects the parent.",{"type":48,"tag":210,"props":274,"children":275},{},[276,281,283,289],{"type":48,"tag":53,"props":277,"children":278},{},[279],{"type":57,"value":280},"Webhooks, bots, and post-response work.",{"type":57,"value":282}," Webhook handlers that fan out into multiple DB writes, Discord\u002FWebSocket bots, and fire-and-forget follow-ups via ",{"type":48,"tag":62,"props":284,"children":286},{"className":285},[],[287],{"type":57,"value":288},"waitUntil",{"type":57,"value":290}," (analytics, audit logs) all fit.",{"type":48,"tag":49,"props":292,"children":293},{},[294,296,301,303,309,311,317],{"type":57,"value":295},"If the workload is a pure static site, a cron\u002Fbackground job that needs its own lifecycle and cancellation, or something that must run outside ",{"type":48,"tag":62,"props":297,"children":299},{"className":298},[],[300],{"type":57,"value":156},{"type":57,"value":302}," today, this isn't the right tool yet (see ",{"type":48,"tag":82,"props":304,"children":306},{"href":305},"#timeouts-and-runtime-limits",[307],{"type":57,"value":308},"Timeouts and Runtime Limits",{"type":57,"value":310}," and ",{"type":48,"tag":82,"props":312,"children":314},{"href":313},"#availability",[315],{"type":57,"value":316},"Availability",{"type":57,"value":318},").",{"type":48,"tag":194,"props":320,"children":322},{"id":321},"what-it-does",[323],{"type":57,"value":324},"What It Does",{"type":48,"tag":206,"props":326,"children":327},{},[328,354,388,405,415],{"type":48,"tag":210,"props":329,"children":330},{},[331,336,338,344,346,352],{"type":48,"tag":53,"props":332,"children":333},{},[334],{"type":57,"value":335},"Long-running & serverless",{"type":57,"value":337}," — Built for WebSocket servers (see ",{"type":48,"tag":82,"props":339,"children":341},{"href":340},"#websocket-servers",[342],{"type":57,"value":343},"WebSocket Servers",{"type":57,"value":345},"), SSE endpoints (see ",{"type":48,"tag":82,"props":347,"children":349},{"href":348},"#server-sent-events-sse",[350],{"type":57,"value":351},"Server-Sent Events (SSE)",{"type":57,"value":353},"), long agent HTTP streams, and APIs. Still scales to zero when idle.",{"type":48,"tag":210,"props":355,"children":356},{},[357,362,364,370,372,378,380,386],{"type":48,"tag":53,"props":358,"children":359},{},[360],{"type":57,"value":361},"Web-standard handler",{"type":57,"value":363}," — A function is any default export with a ",{"type":48,"tag":62,"props":365,"children":367},{"className":366},[],[368],{"type":57,"value":369},"fetch(request)",{"type":57,"value":371}," method returning a ",{"type":48,"tag":62,"props":373,"children":375},{"className":374},[],[376],{"type":57,"value":377},"Response",{"type":57,"value":379}," (Workers\u002FWinterTC-compatible). A Hono app exports exactly that shape, so ",{"type":48,"tag":62,"props":381,"children":383},{"className":382},[],[384],{"type":57,"value":385},"export default app",{"type":57,"value":387}," just works. Runs on Node.js 24, so all Node APIs are available.",{"type":48,"tag":210,"props":389,"children":390},{},[391,396,398,403],{"type":48,"tag":53,"props":392,"children":393},{},[394],{"type":57,"value":395},"Close to your database",{"type":57,"value":397}," — Runs in the branch's region; ",{"type":48,"tag":62,"props":399,"children":401},{"className":400},[],[402],{"type":57,"value":169},{"type":57,"value":404}," injected automatically when the branch has Postgres.",{"type":48,"tag":210,"props":406,"children":407},{},[408,413],{"type":48,"tag":53,"props":409,"children":410},{},[411],{"type":57,"value":412},"Branchable",{"type":57,"value":414}," — Each branch runs its own function version at its own URL against its own isolated state.",{"type":48,"tag":210,"props":416,"children":417},{},[418,423,425,430,432,437],{"type":48,"tag":53,"props":419,"children":420},{},[421],{"type":57,"value":422},"Same CLI\u002FAPI",{"type":57,"value":424}," — Deploy and manage via ",{"type":48,"tag":62,"props":426,"children":428},{"className":427},[],[429],{"type":57,"value":8},{"type":57,"value":431},", ",{"type":48,"tag":62,"props":433,"children":435},{"className":434},[],[436],{"type":57,"value":177},{"type":57,"value":438},", or the Neon API.",{"type":48,"tag":194,"props":440,"children":442},{"id":441},"availability",[443],{"type":57,"value":316},{"type":48,"tag":49,"props":445,"children":446},{},[447,449,454,456,461],{"type":57,"value":448},"Check this precondition before setting anything up: Neon Functions is a public beta feature available only on new projects in the ",{"type":48,"tag":62,"props":450,"children":452},{"className":451},[],[453],{"type":57,"value":156},{"type":57,"value":455}," region. Confirm the user's Neon project is a new project in ",{"type":48,"tag":62,"props":457,"children":459},{"className":458},[],[460],{"type":57,"value":156},{"type":57,"value":462},"; it can't be enabled on existing projects. Functions usage isn't billed during the public beta.",{"type":48,"tag":194,"props":464,"children":466},{"id":465},"architecture-where-functions-fit",[467],{"type":57,"value":468},"Architecture: Where Functions Fit",{"type":48,"tag":49,"props":470,"children":471},{},[472,474,479,481,486],{"type":57,"value":473},"Neon (Functions included) is ",{"type":48,"tag":53,"props":475,"children":476},{},[477],{"type":57,"value":478},"backend primitives, not full-stack app hosting",{"type":57,"value":480},". Host your app on ",{"type":48,"tag":53,"props":482,"children":483},{},[484],{"type":57,"value":485},"Vercel",{"type":57,"value":487}," (or Netlify, or another frontend\u002Fapp host); Functions are the long-running, stateful slice of your backend that lives next to your data. They compose with that platform in two ways:",{"type":48,"tag":206,"props":489,"children":490},{},[491,509],{"type":48,"tag":210,"props":492,"children":493},{},[494,499,501,507],{"type":48,"tag":53,"props":495,"children":496},{},[497],{"type":57,"value":498},"Add a Function to a full-stack app.",{"type":57,"value":500}," Your Next.js \u002F TanStack Start app on Vercel (or Netlify) owns UI, auth (e.g. Neon Auth), and talks directly to Neon Postgres and Object Storage. When one workload outgrows the host's short serverless limits — a WebSocket or SSE server, or a long-running agent that would time out — move just that piece onto a Neon Function. (See ",{"type":48,"tag":82,"props":502,"children":504},{"href":503},"#functions-as-an-agent-backend-nextjs-and-similar-frameworks",[505],{"type":57,"value":506},"Functions as an Agent Backend",{"type":57,"value":508}," for the client-direct pattern.)",{"type":48,"tag":210,"props":510,"children":511},{},[512,517,519,524,526,531,533,538],{"type":48,"tag":53,"props":513,"children":514},{},[515],{"type":57,"value":516},"Run the whole backend control plane on Functions.",{"type":57,"value":518}," Especially when the frontend is ",{"type":48,"tag":53,"props":520,"children":521},{},[522],{"type":57,"value":523},"client-only",{"type":57,"value":525}," — TanStack Router, React Router in client mode, and similar SPAs hosted on Vercel or Netlify — the client calls Functions ",{"type":48,"tag":53,"props":527,"children":528},{},[529],{"type":57,"value":530},"directly",{"type":57,"value":532},". Build REST APIs and request\u002Fresponse agents, host ",{"type":48,"tag":53,"props":534,"children":535},{},[536],{"type":57,"value":537},"MCP servers",{"type":57,"value":539},", and run anything stateful or that belongs close to Postgres and Object Storage.",{"type":48,"tag":49,"props":541,"children":542},{},[543,545,549,551,556],{"type":57,"value":544},"Either way, secure a Function like any standalone REST API: verify a JWT or API key at the top of the handler (see the WARNING under ",{"type":48,"tag":82,"props":546,"children":547},{"href":503},[548],{"type":57,"value":506},{"type":57,"value":550},"). Because a Function is just your backend, you can ",{"type":48,"tag":53,"props":552,"children":553},{},[554],{"type":57,"value":555},"move pieces between your host and Neon",{"type":57,"value":557}," — relocate an agent or a stateful WebSocket server onto a Function when it needs more runtime, and back if needed.",{"type":48,"tag":194,"props":559,"children":561},{"id":560},"setup",[562],{"type":57,"value":563},"Setup",{"type":48,"tag":49,"props":565,"children":566},{},[567,569,574,576,581,583,588,590,596,598,604,606,611],{"type":57,"value":568},"Functions are declared in ",{"type":48,"tag":62,"props":570,"children":572},{"className":571},[],[573],{"type":57,"value":177},{"type":57,"value":575}," (see the ",{"type":48,"tag":62,"props":577,"children":579},{"className":578},[],[580],{"type":57,"value":8},{"type":57,"value":582}," skill for the branch-first workflow and ",{"type":48,"tag":62,"props":584,"children":586},{"className":585},[],[587],{"type":57,"value":177},{"type":57,"value":589}," basics). Add ",{"type":48,"tag":62,"props":591,"children":593},{"className":592},[],[594],{"type":57,"value":595},"@neon\u002Fconfig",{"type":57,"value":597}," and declare functions under ",{"type":48,"tag":62,"props":599,"children":601},{"className":600},[],[602],{"type":57,"value":603},"preview.functions",{"type":57,"value":605},", keyed by ",{"type":48,"tag":53,"props":607,"children":608},{},[609],{"type":57,"value":610},"slug",{"type":57,"value":612},":",{"type":48,"tag":92,"props":614,"children":618},{"className":615,"code":616,"language":617,"meta":97,"style":97},"language-typescript shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","\u002F\u002F neon.ts\nimport { defineConfig } from \"@neon\u002Fconfig\u002Fv1\";\n\nexport default defineConfig({\n  preview: {\n    functions: {\n      todos: {\n        \u002F\u002F slug: ^[a-z0-9]{1,20}$ — lowercase letters\u002Fdigits, no hyphens\n        name: \"todo api\", \u002F\u002F display label only\n        source: \"src\u002Findex.ts\", \u002F\u002F entry file, relative to neon.ts\n      },\n    },\n  },\n});\n","typescript",[619],{"type":48,"tag":62,"props":620,"children":621},{"__ignoreMap":97},[622,631,683,693,722,741,758,775,784,820,855,864,872,881],{"type":48,"tag":103,"props":623,"children":624},{"class":105,"line":106},[625],{"type":48,"tag":103,"props":626,"children":628},{"style":627},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[629],{"type":57,"value":630},"\u002F\u002F neon.ts\n",{"type":48,"tag":103,"props":632,"children":634},{"class":105,"line":633},2,[635,641,647,653,658,663,668,673,678],{"type":48,"tag":103,"props":636,"children":638},{"style":637},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[639],{"type":57,"value":640},"import",{"type":48,"tag":103,"props":642,"children":644},{"style":643},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[645],{"type":57,"value":646}," {",{"type":48,"tag":103,"props":648,"children":650},{"style":649},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[651],{"type":57,"value":652}," defineConfig",{"type":48,"tag":103,"props":654,"children":655},{"style":643},[656],{"type":57,"value":657}," }",{"type":48,"tag":103,"props":659,"children":660},{"style":637},[661],{"type":57,"value":662}," from",{"type":48,"tag":103,"props":664,"children":665},{"style":643},[666],{"type":57,"value":667}," \"",{"type":48,"tag":103,"props":669,"children":670},{"style":116},[671],{"type":57,"value":672},"@neon\u002Fconfig\u002Fv1",{"type":48,"tag":103,"props":674,"children":675},{"style":643},[676],{"type":57,"value":677},"\"",{"type":48,"tag":103,"props":679,"children":680},{"style":643},[681],{"type":57,"value":682},";\n",{"type":48,"tag":103,"props":684,"children":686},{"class":105,"line":685},3,[687],{"type":48,"tag":103,"props":688,"children":690},{"emptyLinePlaceholder":689},true,[691],{"type":57,"value":692},"\n",{"type":48,"tag":103,"props":694,"children":696},{"class":105,"line":695},4,[697,702,707,712,717],{"type":48,"tag":103,"props":698,"children":699},{"style":637},[700],{"type":57,"value":701},"export",{"type":48,"tag":103,"props":703,"children":704},{"style":637},[705],{"type":57,"value":706}," default",{"type":48,"tag":103,"props":708,"children":710},{"style":709},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[711],{"type":57,"value":652},{"type":48,"tag":103,"props":713,"children":714},{"style":649},[715],{"type":57,"value":716},"(",{"type":48,"tag":103,"props":718,"children":719},{"style":643},[720],{"type":57,"value":721},"{\n",{"type":48,"tag":103,"props":723,"children":725},{"class":105,"line":724},5,[726,732,736],{"type":48,"tag":103,"props":727,"children":729},{"style":728},"--shiki-light:#E53935;--shiki-default:#F07178;--shiki-dark:#F07178",[730],{"type":57,"value":731},"  preview",{"type":48,"tag":103,"props":733,"children":734},{"style":643},[735],{"type":57,"value":612},{"type":48,"tag":103,"props":737,"children":738},{"style":643},[739],{"type":57,"value":740}," {\n",{"type":48,"tag":103,"props":742,"children":744},{"class":105,"line":743},6,[745,750,754],{"type":48,"tag":103,"props":746,"children":747},{"style":728},[748],{"type":57,"value":749},"    functions",{"type":48,"tag":103,"props":751,"children":752},{"style":643},[753],{"type":57,"value":612},{"type":48,"tag":103,"props":755,"children":756},{"style":643},[757],{"type":57,"value":740},{"type":48,"tag":103,"props":759,"children":761},{"class":105,"line":760},7,[762,767,771],{"type":48,"tag":103,"props":763,"children":764},{"style":728},[765],{"type":57,"value":766},"      todos",{"type":48,"tag":103,"props":768,"children":769},{"style":643},[770],{"type":57,"value":612},{"type":48,"tag":103,"props":772,"children":773},{"style":643},[774],{"type":57,"value":740},{"type":48,"tag":103,"props":776,"children":778},{"class":105,"line":777},8,[779],{"type":48,"tag":103,"props":780,"children":781},{"style":627},[782],{"type":57,"value":783},"        \u002F\u002F slug: ^[a-z0-9]{1,20}$ — lowercase letters\u002Fdigits, no hyphens\n",{"type":48,"tag":103,"props":785,"children":787},{"class":105,"line":786},9,[788,793,797,801,806,810,815],{"type":48,"tag":103,"props":789,"children":790},{"style":728},[791],{"type":57,"value":792},"        name",{"type":48,"tag":103,"props":794,"children":795},{"style":643},[796],{"type":57,"value":612},{"type":48,"tag":103,"props":798,"children":799},{"style":643},[800],{"type":57,"value":667},{"type":48,"tag":103,"props":802,"children":803},{"style":116},[804],{"type":57,"value":805},"todo api",{"type":48,"tag":103,"props":807,"children":808},{"style":643},[809],{"type":57,"value":677},{"type":48,"tag":103,"props":811,"children":812},{"style":643},[813],{"type":57,"value":814},",",{"type":48,"tag":103,"props":816,"children":817},{"style":627},[818],{"type":57,"value":819}," \u002F\u002F display label only\n",{"type":48,"tag":103,"props":821,"children":823},{"class":105,"line":822},10,[824,829,833,837,842,846,850],{"type":48,"tag":103,"props":825,"children":826},{"style":728},[827],{"type":57,"value":828},"        source",{"type":48,"tag":103,"props":830,"children":831},{"style":643},[832],{"type":57,"value":612},{"type":48,"tag":103,"props":834,"children":835},{"style":643},[836],{"type":57,"value":667},{"type":48,"tag":103,"props":838,"children":839},{"style":116},[840],{"type":57,"value":841},"src\u002Findex.ts",{"type":48,"tag":103,"props":843,"children":844},{"style":643},[845],{"type":57,"value":677},{"type":48,"tag":103,"props":847,"children":848},{"style":643},[849],{"type":57,"value":814},{"type":48,"tag":103,"props":851,"children":852},{"style":627},[853],{"type":57,"value":854}," \u002F\u002F entry file, relative to neon.ts\n",{"type":48,"tag":103,"props":856,"children":858},{"class":105,"line":857},11,[859],{"type":48,"tag":103,"props":860,"children":861},{"style":643},[862],{"type":57,"value":863},"      },\n",{"type":48,"tag":103,"props":865,"children":866},{"class":105,"line":34},[867],{"type":48,"tag":103,"props":868,"children":869},{"style":643},[870],{"type":57,"value":871},"    },\n",{"type":48,"tag":103,"props":873,"children":875},{"class":105,"line":874},13,[876],{"type":48,"tag":103,"props":877,"children":878},{"style":643},[879],{"type":57,"value":880},"  },\n",{"type":48,"tag":103,"props":882,"children":884},{"class":105,"line":883},14,[885,890,895],{"type":48,"tag":103,"props":886,"children":887},{"style":643},[888],{"type":57,"value":889},"}",{"type":48,"tag":103,"props":891,"children":892},{"style":649},[893],{"type":57,"value":894},")",{"type":48,"tag":103,"props":896,"children":897},{"style":643},[898],{"type":57,"value":682},{"type":48,"tag":49,"props":900,"children":901},{},[902,904,910],{"type":57,"value":903},"The slug is the function's permanent identity (it appears in the invocation URL and CLI commands) and can't be changed after the first deploy. Use ",{"type":48,"tag":62,"props":905,"children":907},{"className":906},[],[908],{"type":57,"value":909},"name",{"type":57,"value":911}," for a human-readable label.",{"type":48,"tag":49,"props":913,"children":914},{},[915,917,922],{"type":57,"value":916},"A minimal function — a Hono app that queries the branch's Postgres via the injected ",{"type":48,"tag":62,"props":918,"children":920},{"className":919},[],[921],{"type":57,"value":169},{"type":57,"value":612},{"type":48,"tag":92,"props":924,"children":926},{"className":615,"code":925,"language":617,"meta":97,"style":97},"\u002F\u002F src\u002Findex.ts\nimport { Hono } from \"hono\";\nimport { drizzle } from \"drizzle-orm\u002Fnode-postgres\";\nimport { Pool } from \"pg\";\nimport { parseEnv } from \"@neon\u002Fenv\";\nimport config from \"..\u002Fneon\";\nimport { todos } from \".\u002Fdb\u002Fschema\";\n\nconst env = parseEnv(config);\nconst pool = new Pool({ connectionString: env.postgres.databaseUrl, max: 5 });\nconst db = drizzle(pool);\n\nconst app = new Hono();\napp.get(\"\u002F\", (c) => c.text(\"Neon + Hono + Drizzle\"));\napp.post(\"\u002Ftodos\", async (c) => {\n  const { text } = await c.req.json\u003C{ text: string }>();\n  const [row] = await db.insert(todos).values({ text }).returning();\n  return c.json(row, 201);\n});\napp.get(\"\u002Ftodos\", async (c) => c.json(await db.select().from(todos)));\n\nexport default app;\n",[927],{"type":48,"tag":62,"props":928,"children":929},{"__ignoreMap":97},[930,938,979,1020,1060,1101,1135,1176,1183,1215,1312,1341,1348,1381,1478,1541,1626,1730,1776,1792,1903,1911],{"type":48,"tag":103,"props":931,"children":932},{"class":105,"line":106},[933],{"type":48,"tag":103,"props":934,"children":935},{"style":627},[936],{"type":57,"value":937},"\u002F\u002F src\u002Findex.ts\n",{"type":48,"tag":103,"props":939,"children":940},{"class":105,"line":633},[941,945,949,954,958,962,966,971,975],{"type":48,"tag":103,"props":942,"children":943},{"style":637},[944],{"type":57,"value":640},{"type":48,"tag":103,"props":946,"children":947},{"style":643},[948],{"type":57,"value":646},{"type":48,"tag":103,"props":950,"children":951},{"style":649},[952],{"type":57,"value":953}," Hono",{"type":48,"tag":103,"props":955,"children":956},{"style":643},[957],{"type":57,"value":657},{"type":48,"tag":103,"props":959,"children":960},{"style":637},[961],{"type":57,"value":662},{"type":48,"tag":103,"props":963,"children":964},{"style":643},[965],{"type":57,"value":667},{"type":48,"tag":103,"props":967,"children":968},{"style":116},[969],{"type":57,"value":970},"hono",{"type":48,"tag":103,"props":972,"children":973},{"style":643},[974],{"type":57,"value":677},{"type":48,"tag":103,"props":976,"children":977},{"style":643},[978],{"type":57,"value":682},{"type":48,"tag":103,"props":980,"children":981},{"class":105,"line":685},[982,986,990,995,999,1003,1007,1012,1016],{"type":48,"tag":103,"props":983,"children":984},{"style":637},[985],{"type":57,"value":640},{"type":48,"tag":103,"props":987,"children":988},{"style":643},[989],{"type":57,"value":646},{"type":48,"tag":103,"props":991,"children":992},{"style":649},[993],{"type":57,"value":994}," drizzle",{"type":48,"tag":103,"props":996,"children":997},{"style":643},[998],{"type":57,"value":657},{"type":48,"tag":103,"props":1000,"children":1001},{"style":637},[1002],{"type":57,"value":662},{"type":48,"tag":103,"props":1004,"children":1005},{"style":643},[1006],{"type":57,"value":667},{"type":48,"tag":103,"props":1008,"children":1009},{"style":116},[1010],{"type":57,"value":1011},"drizzle-orm\u002Fnode-postgres",{"type":48,"tag":103,"props":1013,"children":1014},{"style":643},[1015],{"type":57,"value":677},{"type":48,"tag":103,"props":1017,"children":1018},{"style":643},[1019],{"type":57,"value":682},{"type":48,"tag":103,"props":1021,"children":1022},{"class":105,"line":695},[1023,1027,1031,1036,1040,1044,1048,1052,1056],{"type":48,"tag":103,"props":1024,"children":1025},{"style":637},[1026],{"type":57,"value":640},{"type":48,"tag":103,"props":1028,"children":1029},{"style":643},[1030],{"type":57,"value":646},{"type":48,"tag":103,"props":1032,"children":1033},{"style":649},[1034],{"type":57,"value":1035}," Pool",{"type":48,"tag":103,"props":1037,"children":1038},{"style":643},[1039],{"type":57,"value":657},{"type":48,"tag":103,"props":1041,"children":1042},{"style":637},[1043],{"type":57,"value":662},{"type":48,"tag":103,"props":1045,"children":1046},{"style":643},[1047],{"type":57,"value":667},{"type":48,"tag":103,"props":1049,"children":1050},{"style":116},[1051],{"type":57,"value":243},{"type":48,"tag":103,"props":1053,"children":1054},{"style":643},[1055],{"type":57,"value":677},{"type":48,"tag":103,"props":1057,"children":1058},{"style":643},[1059],{"type":57,"value":682},{"type":48,"tag":103,"props":1061,"children":1062},{"class":105,"line":724},[1063,1067,1071,1076,1080,1084,1088,1093,1097],{"type":48,"tag":103,"props":1064,"children":1065},{"style":637},[1066],{"type":57,"value":640},{"type":48,"tag":103,"props":1068,"children":1069},{"style":643},[1070],{"type":57,"value":646},{"type":48,"tag":103,"props":1072,"children":1073},{"style":649},[1074],{"type":57,"value":1075}," parseEnv",{"type":48,"tag":103,"props":1077,"children":1078},{"style":643},[1079],{"type":57,"value":657},{"type":48,"tag":103,"props":1081,"children":1082},{"style":637},[1083],{"type":57,"value":662},{"type":48,"tag":103,"props":1085,"children":1086},{"style":643},[1087],{"type":57,"value":667},{"type":48,"tag":103,"props":1089,"children":1090},{"style":116},[1091],{"type":57,"value":1092},"@neon\u002Fenv",{"type":48,"tag":103,"props":1094,"children":1095},{"style":643},[1096],{"type":57,"value":677},{"type":48,"tag":103,"props":1098,"children":1099},{"style":643},[1100],{"type":57,"value":682},{"type":48,"tag":103,"props":1102,"children":1103},{"class":105,"line":743},[1104,1108,1113,1118,1122,1127,1131],{"type":48,"tag":103,"props":1105,"children":1106},{"style":637},[1107],{"type":57,"value":640},{"type":48,"tag":103,"props":1109,"children":1110},{"style":649},[1111],{"type":57,"value":1112}," config ",{"type":48,"tag":103,"props":1114,"children":1115},{"style":637},[1116],{"type":57,"value":1117},"from",{"type":48,"tag":103,"props":1119,"children":1120},{"style":643},[1121],{"type":57,"value":667},{"type":48,"tag":103,"props":1123,"children":1124},{"style":116},[1125],{"type":57,"value":1126},"..\u002Fneon",{"type":48,"tag":103,"props":1128,"children":1129},{"style":643},[1130],{"type":57,"value":677},{"type":48,"tag":103,"props":1132,"children":1133},{"style":643},[1134],{"type":57,"value":682},{"type":48,"tag":103,"props":1136,"children":1137},{"class":105,"line":760},[1138,1142,1146,1151,1155,1159,1163,1168,1172],{"type":48,"tag":103,"props":1139,"children":1140},{"style":637},[1141],{"type":57,"value":640},{"type":48,"tag":103,"props":1143,"children":1144},{"style":643},[1145],{"type":57,"value":646},{"type":48,"tag":103,"props":1147,"children":1148},{"style":649},[1149],{"type":57,"value":1150}," todos",{"type":48,"tag":103,"props":1152,"children":1153},{"style":643},[1154],{"type":57,"value":657},{"type":48,"tag":103,"props":1156,"children":1157},{"style":637},[1158],{"type":57,"value":662},{"type":48,"tag":103,"props":1160,"children":1161},{"style":643},[1162],{"type":57,"value":667},{"type":48,"tag":103,"props":1164,"children":1165},{"style":116},[1166],{"type":57,"value":1167},".\u002Fdb\u002Fschema",{"type":48,"tag":103,"props":1169,"children":1170},{"style":643},[1171],{"type":57,"value":677},{"type":48,"tag":103,"props":1173,"children":1174},{"style":643},[1175],{"type":57,"value":682},{"type":48,"tag":103,"props":1177,"children":1178},{"class":105,"line":777},[1179],{"type":48,"tag":103,"props":1180,"children":1181},{"emptyLinePlaceholder":689},[1182],{"type":57,"value":692},{"type":48,"tag":103,"props":1184,"children":1185},{"class":105,"line":786},[1186,1192,1197,1202,1206,1211],{"type":48,"tag":103,"props":1187,"children":1189},{"style":1188},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1190],{"type":57,"value":1191},"const",{"type":48,"tag":103,"props":1193,"children":1194},{"style":649},[1195],{"type":57,"value":1196}," env ",{"type":48,"tag":103,"props":1198,"children":1199},{"style":643},[1200],{"type":57,"value":1201},"=",{"type":48,"tag":103,"props":1203,"children":1204},{"style":709},[1205],{"type":57,"value":1075},{"type":48,"tag":103,"props":1207,"children":1208},{"style":649},[1209],{"type":57,"value":1210},"(config)",{"type":48,"tag":103,"props":1212,"children":1213},{"style":643},[1214],{"type":57,"value":682},{"type":48,"tag":103,"props":1216,"children":1217},{"class":105,"line":822},[1218,1222,1227,1231,1236,1240,1244,1249,1254,1258,1263,1267,1272,1276,1281,1285,1290,1294,1300,1304,1308],{"type":48,"tag":103,"props":1219,"children":1220},{"style":1188},[1221],{"type":57,"value":1191},{"type":48,"tag":103,"props":1223,"children":1224},{"style":649},[1225],{"type":57,"value":1226}," pool ",{"type":48,"tag":103,"props":1228,"children":1229},{"style":643},[1230],{"type":57,"value":1201},{"type":48,"tag":103,"props":1232,"children":1233},{"style":643},[1234],{"type":57,"value":1235}," new",{"type":48,"tag":103,"props":1237,"children":1238},{"style":709},[1239],{"type":57,"value":1035},{"type":48,"tag":103,"props":1241,"children":1242},{"style":649},[1243],{"type":57,"value":716},{"type":48,"tag":103,"props":1245,"children":1246},{"style":643},[1247],{"type":57,"value":1248},"{",{"type":48,"tag":103,"props":1250,"children":1251},{"style":728},[1252],{"type":57,"value":1253}," connectionString",{"type":48,"tag":103,"props":1255,"children":1256},{"style":643},[1257],{"type":57,"value":612},{"type":48,"tag":103,"props":1259,"children":1260},{"style":649},[1261],{"type":57,"value":1262}," env",{"type":48,"tag":103,"props":1264,"children":1265},{"style":643},[1266],{"type":57,"value":158},{"type":48,"tag":103,"props":1268,"children":1269},{"style":649},[1270],{"type":57,"value":1271},"postgres",{"type":48,"tag":103,"props":1273,"children":1274},{"style":643},[1275],{"type":57,"value":158},{"type":48,"tag":103,"props":1277,"children":1278},{"style":649},[1279],{"type":57,"value":1280},"databaseUrl",{"type":48,"tag":103,"props":1282,"children":1283},{"style":643},[1284],{"type":57,"value":814},{"type":48,"tag":103,"props":1286,"children":1287},{"style":728},[1288],{"type":57,"value":1289}," max",{"type":48,"tag":103,"props":1291,"children":1292},{"style":643},[1293],{"type":57,"value":612},{"type":48,"tag":103,"props":1295,"children":1297},{"style":1296},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1298],{"type":57,"value":1299}," 5",{"type":48,"tag":103,"props":1301,"children":1302},{"style":643},[1303],{"type":57,"value":657},{"type":48,"tag":103,"props":1305,"children":1306},{"style":649},[1307],{"type":57,"value":894},{"type":48,"tag":103,"props":1309,"children":1310},{"style":643},[1311],{"type":57,"value":682},{"type":48,"tag":103,"props":1313,"children":1314},{"class":105,"line":857},[1315,1319,1324,1328,1332,1337],{"type":48,"tag":103,"props":1316,"children":1317},{"style":1188},[1318],{"type":57,"value":1191},{"type":48,"tag":103,"props":1320,"children":1321},{"style":649},[1322],{"type":57,"value":1323}," db ",{"type":48,"tag":103,"props":1325,"children":1326},{"style":643},[1327],{"type":57,"value":1201},{"type":48,"tag":103,"props":1329,"children":1330},{"style":709},[1331],{"type":57,"value":994},{"type":48,"tag":103,"props":1333,"children":1334},{"style":649},[1335],{"type":57,"value":1336},"(pool)",{"type":48,"tag":103,"props":1338,"children":1339},{"style":643},[1340],{"type":57,"value":682},{"type":48,"tag":103,"props":1342,"children":1343},{"class":105,"line":34},[1344],{"type":48,"tag":103,"props":1345,"children":1346},{"emptyLinePlaceholder":689},[1347],{"type":57,"value":692},{"type":48,"tag":103,"props":1349,"children":1350},{"class":105,"line":874},[1351,1355,1360,1364,1368,1372,1377],{"type":48,"tag":103,"props":1352,"children":1353},{"style":1188},[1354],{"type":57,"value":1191},{"type":48,"tag":103,"props":1356,"children":1357},{"style":649},[1358],{"type":57,"value":1359}," app ",{"type":48,"tag":103,"props":1361,"children":1362},{"style":643},[1363],{"type":57,"value":1201},{"type":48,"tag":103,"props":1365,"children":1366},{"style":643},[1367],{"type":57,"value":1235},{"type":48,"tag":103,"props":1369,"children":1370},{"style":709},[1371],{"type":57,"value":953},{"type":48,"tag":103,"props":1373,"children":1374},{"style":649},[1375],{"type":57,"value":1376},"()",{"type":48,"tag":103,"props":1378,"children":1379},{"style":643},[1380],{"type":57,"value":682},{"type":48,"tag":103,"props":1382,"children":1383},{"class":105,"line":883},[1384,1389,1393,1398,1402,1406,1411,1415,1419,1424,1430,1434,1439,1444,1448,1452,1456,1460,1465,1469,1474],{"type":48,"tag":103,"props":1385,"children":1386},{"style":649},[1387],{"type":57,"value":1388},"app",{"type":48,"tag":103,"props":1390,"children":1391},{"style":643},[1392],{"type":57,"value":158},{"type":48,"tag":103,"props":1394,"children":1395},{"style":709},[1396],{"type":57,"value":1397},"get",{"type":48,"tag":103,"props":1399,"children":1400},{"style":649},[1401],{"type":57,"value":716},{"type":48,"tag":103,"props":1403,"children":1404},{"style":643},[1405],{"type":57,"value":677},{"type":48,"tag":103,"props":1407,"children":1408},{"style":116},[1409],{"type":57,"value":1410},"\u002F",{"type":48,"tag":103,"props":1412,"children":1413},{"style":643},[1414],{"type":57,"value":677},{"type":48,"tag":103,"props":1416,"children":1417},{"style":643},[1418],{"type":57,"value":814},{"type":48,"tag":103,"props":1420,"children":1421},{"style":643},[1422],{"type":57,"value":1423}," (",{"type":48,"tag":103,"props":1425,"children":1427},{"style":1426},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#EEFFFF;--shiki-default-font-style:italic;--shiki-dark:#BABED8;--shiki-dark-font-style:italic",[1428],{"type":57,"value":1429},"c",{"type":48,"tag":103,"props":1431,"children":1432},{"style":643},[1433],{"type":57,"value":894},{"type":48,"tag":103,"props":1435,"children":1436},{"style":1188},[1437],{"type":57,"value":1438}," =>",{"type":48,"tag":103,"props":1440,"children":1441},{"style":649},[1442],{"type":57,"value":1443}," c",{"type":48,"tag":103,"props":1445,"children":1446},{"style":643},[1447],{"type":57,"value":158},{"type":48,"tag":103,"props":1449,"children":1450},{"style":709},[1451],{"type":57,"value":57},{"type":48,"tag":103,"props":1453,"children":1454},{"style":649},[1455],{"type":57,"value":716},{"type":48,"tag":103,"props":1457,"children":1458},{"style":643},[1459],{"type":57,"value":677},{"type":48,"tag":103,"props":1461,"children":1462},{"style":116},[1463],{"type":57,"value":1464},"Neon + Hono + Drizzle",{"type":48,"tag":103,"props":1466,"children":1467},{"style":643},[1468],{"type":57,"value":677},{"type":48,"tag":103,"props":1470,"children":1471},{"style":649},[1472],{"type":57,"value":1473},"))",{"type":48,"tag":103,"props":1475,"children":1476},{"style":643},[1477],{"type":57,"value":682},{"type":48,"tag":103,"props":1479,"children":1481},{"class":105,"line":1480},15,[1482,1486,1490,1495,1499,1503,1508,1512,1516,1521,1525,1529,1533,1537],{"type":48,"tag":103,"props":1483,"children":1484},{"style":649},[1485],{"type":57,"value":1388},{"type":48,"tag":103,"props":1487,"children":1488},{"style":643},[1489],{"type":57,"value":158},{"type":48,"tag":103,"props":1491,"children":1492},{"style":709},[1493],{"type":57,"value":1494},"post",{"type":48,"tag":103,"props":1496,"children":1497},{"style":649},[1498],{"type":57,"value":716},{"type":48,"tag":103,"props":1500,"children":1501},{"style":643},[1502],{"type":57,"value":677},{"type":48,"tag":103,"props":1504,"children":1505},{"style":116},[1506],{"type":57,"value":1507},"\u002Ftodos",{"type":48,"tag":103,"props":1509,"children":1510},{"style":643},[1511],{"type":57,"value":677},{"type":48,"tag":103,"props":1513,"children":1514},{"style":643},[1515],{"type":57,"value":814},{"type":48,"tag":103,"props":1517,"children":1518},{"style":1188},[1519],{"type":57,"value":1520}," async",{"type":48,"tag":103,"props":1522,"children":1523},{"style":643},[1524],{"type":57,"value":1423},{"type":48,"tag":103,"props":1526,"children":1527},{"style":1426},[1528],{"type":57,"value":1429},{"type":48,"tag":103,"props":1530,"children":1531},{"style":643},[1532],{"type":57,"value":894},{"type":48,"tag":103,"props":1534,"children":1535},{"style":1188},[1536],{"type":57,"value":1438},{"type":48,"tag":103,"props":1538,"children":1539},{"style":643},[1540],{"type":57,"value":740},{"type":48,"tag":103,"props":1542,"children":1544},{"class":105,"line":1543},16,[1545,1550,1554,1559,1563,1568,1573,1577,1581,1586,1590,1595,1600,1604,1608,1613,1618,1622],{"type":48,"tag":103,"props":1546,"children":1547},{"style":1188},[1548],{"type":57,"value":1549},"  const",{"type":48,"tag":103,"props":1551,"children":1552},{"style":643},[1553],{"type":57,"value":646},{"type":48,"tag":103,"props":1555,"children":1556},{"style":649},[1557],{"type":57,"value":1558}," text",{"type":48,"tag":103,"props":1560,"children":1561},{"style":643},[1562],{"type":57,"value":657},{"type":48,"tag":103,"props":1564,"children":1565},{"style":643},[1566],{"type":57,"value":1567}," =",{"type":48,"tag":103,"props":1569,"children":1570},{"style":637},[1571],{"type":57,"value":1572}," await",{"type":48,"tag":103,"props":1574,"children":1575},{"style":649},[1576],{"type":57,"value":1443},{"type":48,"tag":103,"props":1578,"children":1579},{"style":643},[1580],{"type":57,"value":158},{"type":48,"tag":103,"props":1582,"children":1583},{"style":649},[1584],{"type":57,"value":1585},"req",{"type":48,"tag":103,"props":1587,"children":1588},{"style":643},[1589],{"type":57,"value":158},{"type":48,"tag":103,"props":1591,"children":1592},{"style":709},[1593],{"type":57,"value":1594},"json",{"type":48,"tag":103,"props":1596,"children":1597},{"style":643},[1598],{"type":57,"value":1599},"\u003C{",{"type":48,"tag":103,"props":1601,"children":1602},{"style":728},[1603],{"type":57,"value":1558},{"type":48,"tag":103,"props":1605,"children":1606},{"style":643},[1607],{"type":57,"value":612},{"type":48,"tag":103,"props":1609,"children":1610},{"style":110},[1611],{"type":57,"value":1612}," string",{"type":48,"tag":103,"props":1614,"children":1615},{"style":643},[1616],{"type":57,"value":1617}," }>",{"type":48,"tag":103,"props":1619,"children":1620},{"style":728},[1621],{"type":57,"value":1376},{"type":48,"tag":103,"props":1623,"children":1624},{"style":643},[1625],{"type":57,"value":682},{"type":48,"tag":103,"props":1627,"children":1629},{"class":105,"line":1628},17,[1630,1634,1639,1644,1649,1653,1657,1662,1666,1671,1675,1680,1684,1688,1693,1697,1701,1705,1709,1713,1717,1722,1726],{"type":48,"tag":103,"props":1631,"children":1632},{"style":1188},[1633],{"type":57,"value":1549},{"type":48,"tag":103,"props":1635,"children":1636},{"style":643},[1637],{"type":57,"value":1638}," [",{"type":48,"tag":103,"props":1640,"children":1641},{"style":649},[1642],{"type":57,"value":1643},"row",{"type":48,"tag":103,"props":1645,"children":1646},{"style":643},[1647],{"type":57,"value":1648},"]",{"type":48,"tag":103,"props":1650,"children":1651},{"style":643},[1652],{"type":57,"value":1567},{"type":48,"tag":103,"props":1654,"children":1655},{"style":637},[1656],{"type":57,"value":1572},{"type":48,"tag":103,"props":1658,"children":1659},{"style":649},[1660],{"type":57,"value":1661}," db",{"type":48,"tag":103,"props":1663,"children":1664},{"style":643},[1665],{"type":57,"value":158},{"type":48,"tag":103,"props":1667,"children":1668},{"style":709},[1669],{"type":57,"value":1670},"insert",{"type":48,"tag":103,"props":1672,"children":1673},{"style":728},[1674],{"type":57,"value":716},{"type":48,"tag":103,"props":1676,"children":1677},{"style":649},[1678],{"type":57,"value":1679},"todos",{"type":48,"tag":103,"props":1681,"children":1682},{"style":728},[1683],{"type":57,"value":894},{"type":48,"tag":103,"props":1685,"children":1686},{"style":643},[1687],{"type":57,"value":158},{"type":48,"tag":103,"props":1689,"children":1690},{"style":709},[1691],{"type":57,"value":1692},"values",{"type":48,"tag":103,"props":1694,"children":1695},{"style":728},[1696],{"type":57,"value":716},{"type":48,"tag":103,"props":1698,"children":1699},{"style":643},[1700],{"type":57,"value":1248},{"type":48,"tag":103,"props":1702,"children":1703},{"style":649},[1704],{"type":57,"value":1558},{"type":48,"tag":103,"props":1706,"children":1707},{"style":643},[1708],{"type":57,"value":657},{"type":48,"tag":103,"props":1710,"children":1711},{"style":728},[1712],{"type":57,"value":894},{"type":48,"tag":103,"props":1714,"children":1715},{"style":643},[1716],{"type":57,"value":158},{"type":48,"tag":103,"props":1718,"children":1719},{"style":709},[1720],{"type":57,"value":1721},"returning",{"type":48,"tag":103,"props":1723,"children":1724},{"style":728},[1725],{"type":57,"value":1376},{"type":48,"tag":103,"props":1727,"children":1728},{"style":643},[1729],{"type":57,"value":682},{"type":48,"tag":103,"props":1731,"children":1733},{"class":105,"line":1732},18,[1734,1739,1743,1747,1751,1755,1759,1763,1768,1772],{"type":48,"tag":103,"props":1735,"children":1736},{"style":637},[1737],{"type":57,"value":1738},"  return",{"type":48,"tag":103,"props":1740,"children":1741},{"style":649},[1742],{"type":57,"value":1443},{"type":48,"tag":103,"props":1744,"children":1745},{"style":643},[1746],{"type":57,"value":158},{"type":48,"tag":103,"props":1748,"children":1749},{"style":709},[1750],{"type":57,"value":1594},{"type":48,"tag":103,"props":1752,"children":1753},{"style":728},[1754],{"type":57,"value":716},{"type":48,"tag":103,"props":1756,"children":1757},{"style":649},[1758],{"type":57,"value":1643},{"type":48,"tag":103,"props":1760,"children":1761},{"style":643},[1762],{"type":57,"value":814},{"type":48,"tag":103,"props":1764,"children":1765},{"style":1296},[1766],{"type":57,"value":1767}," 201",{"type":48,"tag":103,"props":1769,"children":1770},{"style":728},[1771],{"type":57,"value":894},{"type":48,"tag":103,"props":1773,"children":1774},{"style":643},[1775],{"type":57,"value":682},{"type":48,"tag":103,"props":1777,"children":1779},{"class":105,"line":1778},19,[1780,1784,1788],{"type":48,"tag":103,"props":1781,"children":1782},{"style":643},[1783],{"type":57,"value":889},{"type":48,"tag":103,"props":1785,"children":1786},{"style":649},[1787],{"type":57,"value":894},{"type":48,"tag":103,"props":1789,"children":1790},{"style":643},[1791],{"type":57,"value":682},{"type":48,"tag":103,"props":1793,"children":1795},{"class":105,"line":1794},20,[1796,1800,1804,1808,1812,1816,1820,1824,1828,1832,1836,1840,1844,1848,1852,1856,1860,1864,1869,1873,1877,1882,1886,1890,1894,1899],{"type":48,"tag":103,"props":1797,"children":1798},{"style":649},[1799],{"type":57,"value":1388},{"type":48,"tag":103,"props":1801,"children":1802},{"style":643},[1803],{"type":57,"value":158},{"type":48,"tag":103,"props":1805,"children":1806},{"style":709},[1807],{"type":57,"value":1397},{"type":48,"tag":103,"props":1809,"children":1810},{"style":649},[1811],{"type":57,"value":716},{"type":48,"tag":103,"props":1813,"children":1814},{"style":643},[1815],{"type":57,"value":677},{"type":48,"tag":103,"props":1817,"children":1818},{"style":116},[1819],{"type":57,"value":1507},{"type":48,"tag":103,"props":1821,"children":1822},{"style":643},[1823],{"type":57,"value":677},{"type":48,"tag":103,"props":1825,"children":1826},{"style":643},[1827],{"type":57,"value":814},{"type":48,"tag":103,"props":1829,"children":1830},{"style":1188},[1831],{"type":57,"value":1520},{"type":48,"tag":103,"props":1833,"children":1834},{"style":643},[1835],{"type":57,"value":1423},{"type":48,"tag":103,"props":1837,"children":1838},{"style":1426},[1839],{"type":57,"value":1429},{"type":48,"tag":103,"props":1841,"children":1842},{"style":643},[1843],{"type":57,"value":894},{"type":48,"tag":103,"props":1845,"children":1846},{"style":1188},[1847],{"type":57,"value":1438},{"type":48,"tag":103,"props":1849,"children":1850},{"style":649},[1851],{"type":57,"value":1443},{"type":48,"tag":103,"props":1853,"children":1854},{"style":643},[1855],{"type":57,"value":158},{"type":48,"tag":103,"props":1857,"children":1858},{"style":709},[1859],{"type":57,"value":1594},{"type":48,"tag":103,"props":1861,"children":1862},{"style":649},[1863],{"type":57,"value":716},{"type":48,"tag":103,"props":1865,"children":1866},{"style":637},[1867],{"type":57,"value":1868},"await",{"type":48,"tag":103,"props":1870,"children":1871},{"style":649},[1872],{"type":57,"value":1661},{"type":48,"tag":103,"props":1874,"children":1875},{"style":643},[1876],{"type":57,"value":158},{"type":48,"tag":103,"props":1878,"children":1879},{"style":709},[1880],{"type":57,"value":1881},"select",{"type":48,"tag":103,"props":1883,"children":1884},{"style":649},[1885],{"type":57,"value":1376},{"type":48,"tag":103,"props":1887,"children":1888},{"style":643},[1889],{"type":57,"value":158},{"type":48,"tag":103,"props":1891,"children":1892},{"style":709},[1893],{"type":57,"value":1117},{"type":48,"tag":103,"props":1895,"children":1896},{"style":649},[1897],{"type":57,"value":1898},"(todos)))",{"type":48,"tag":103,"props":1900,"children":1901},{"style":643},[1902],{"type":57,"value":682},{"type":48,"tag":103,"props":1904,"children":1906},{"class":105,"line":1905},21,[1907],{"type":48,"tag":103,"props":1908,"children":1909},{"emptyLinePlaceholder":689},[1910],{"type":57,"value":692},{"type":48,"tag":103,"props":1912,"children":1914},{"class":105,"line":1913},22,[1915,1919,1923,1928],{"type":48,"tag":103,"props":1916,"children":1917},{"style":637},[1918],{"type":57,"value":701},{"type":48,"tag":103,"props":1920,"children":1921},{"style":637},[1922],{"type":57,"value":706},{"type":48,"tag":103,"props":1924,"children":1925},{"style":649},[1926],{"type":57,"value":1927}," app",{"type":48,"tag":103,"props":1929,"children":1930},{"style":643},[1931],{"type":57,"value":682},{"type":48,"tag":49,"props":1933,"children":1934},{},[1935,1937,1942,1944,1950],{"type":57,"value":1936},"Create the ",{"type":48,"tag":62,"props":1938,"children":1940},{"className":1939},[],[1941],{"type":57,"value":243},{"type":57,"value":1943}," pool at module scope (reused across requests on the same isolate) and keep ",{"type":48,"tag":62,"props":1945,"children":1947},{"className":1946},[],[1948],{"type":57,"value":1949},"max",{"type":57,"value":1951}," small (e.g. 5), since each isolate keeps its own pool.",{"type":48,"tag":49,"props":1953,"children":1954},{},[1955,1961,1963,1968,1970,1976,1978,1983],{"type":48,"tag":62,"props":1956,"children":1958},{"className":1957},[],[1959],{"type":57,"value":1960},"parseEnv(config)",{"type":57,"value":1962}," requires ",{"type":48,"tag":221,"props":1964,"children":1965},{},[1966],{"type":57,"value":1967},"every",{"type":57,"value":1969}," variable the config implies. A function that only talks to Postgres over the pooled URL can scope it to just that key — ",{"type":48,"tag":62,"props":1971,"children":1973},{"className":1972},[],[1974],{"type":57,"value":1975},"parseEnv",{"type":57,"value":1977}," then validates and returns only what you asked for (the keys autocomplete from your ",{"type":48,"tag":62,"props":1979,"children":1981},{"className":1980},[],[1982],{"type":57,"value":177},{"type":57,"value":1984},"):",{"type":48,"tag":92,"props":1986,"children":1988},{"className":615,"code":1987,"language":617,"meta":97,"style":97},"const { postgres } = parseEnv(config, [\"DATABASE_URL\"]); \u002F\u002F not the unpooled URL, auth, etc.\nconst pool = new Pool({ connectionString: postgres.databaseUrl, max: 5 });\n",[1989],{"type":48,"tag":62,"props":1990,"children":1991},{"__ignoreMap":97},[1992,2060],{"type":48,"tag":103,"props":1993,"children":1994},{"class":105,"line":106},[1995,1999,2003,2008,2012,2016,2020,2025,2029,2033,2037,2041,2045,2050,2055],{"type":48,"tag":103,"props":1996,"children":1997},{"style":1188},[1998],{"type":57,"value":1191},{"type":48,"tag":103,"props":2000,"children":2001},{"style":643},[2002],{"type":57,"value":646},{"type":48,"tag":103,"props":2004,"children":2005},{"style":649},[2006],{"type":57,"value":2007}," postgres ",{"type":48,"tag":103,"props":2009,"children":2010},{"style":643},[2011],{"type":57,"value":889},{"type":48,"tag":103,"props":2013,"children":2014},{"style":643},[2015],{"type":57,"value":1567},{"type":48,"tag":103,"props":2017,"children":2018},{"style":709},[2019],{"type":57,"value":1075},{"type":48,"tag":103,"props":2021,"children":2022},{"style":649},[2023],{"type":57,"value":2024},"(config",{"type":48,"tag":103,"props":2026,"children":2027},{"style":643},[2028],{"type":57,"value":814},{"type":48,"tag":103,"props":2030,"children":2031},{"style":649},[2032],{"type":57,"value":1638},{"type":48,"tag":103,"props":2034,"children":2035},{"style":643},[2036],{"type":57,"value":677},{"type":48,"tag":103,"props":2038,"children":2039},{"style":116},[2040],{"type":57,"value":169},{"type":48,"tag":103,"props":2042,"children":2043},{"style":643},[2044],{"type":57,"value":677},{"type":48,"tag":103,"props":2046,"children":2047},{"style":649},[2048],{"type":57,"value":2049},"])",{"type":48,"tag":103,"props":2051,"children":2052},{"style":643},[2053],{"type":57,"value":2054},";",{"type":48,"tag":103,"props":2056,"children":2057},{"style":627},[2058],{"type":57,"value":2059}," \u002F\u002F not the unpooled URL, auth, etc.\n",{"type":48,"tag":103,"props":2061,"children":2062},{"class":105,"line":633},[2063,2067,2071,2075,2079,2083,2087,2091,2095,2099,2104,2108,2112,2116,2120,2124,2128,2132,2136],{"type":48,"tag":103,"props":2064,"children":2065},{"style":1188},[2066],{"type":57,"value":1191},{"type":48,"tag":103,"props":2068,"children":2069},{"style":649},[2070],{"type":57,"value":1226},{"type":48,"tag":103,"props":2072,"children":2073},{"style":643},[2074],{"type":57,"value":1201},{"type":48,"tag":103,"props":2076,"children":2077},{"style":643},[2078],{"type":57,"value":1235},{"type":48,"tag":103,"props":2080,"children":2081},{"style":709},[2082],{"type":57,"value":1035},{"type":48,"tag":103,"props":2084,"children":2085},{"style":649},[2086],{"type":57,"value":716},{"type":48,"tag":103,"props":2088,"children":2089},{"style":643},[2090],{"type":57,"value":1248},{"type":48,"tag":103,"props":2092,"children":2093},{"style":728},[2094],{"type":57,"value":1253},{"type":48,"tag":103,"props":2096,"children":2097},{"style":643},[2098],{"type":57,"value":612},{"type":48,"tag":103,"props":2100,"children":2101},{"style":649},[2102],{"type":57,"value":2103}," postgres",{"type":48,"tag":103,"props":2105,"children":2106},{"style":643},[2107],{"type":57,"value":158},{"type":48,"tag":103,"props":2109,"children":2110},{"style":649},[2111],{"type":57,"value":1280},{"type":48,"tag":103,"props":2113,"children":2114},{"style":643},[2115],{"type":57,"value":814},{"type":48,"tag":103,"props":2117,"children":2118},{"style":728},[2119],{"type":57,"value":1289},{"type":48,"tag":103,"props":2121,"children":2122},{"style":643},[2123],{"type":57,"value":612},{"type":48,"tag":103,"props":2125,"children":2126},{"style":1296},[2127],{"type":57,"value":1299},{"type":48,"tag":103,"props":2129,"children":2130},{"style":643},[2131],{"type":57,"value":657},{"type":48,"tag":103,"props":2133,"children":2134},{"style":649},[2135],{"type":57,"value":894},{"type":48,"tag":103,"props":2137,"children":2138},{"style":643},[2139],{"type":57,"value":682},{"type":48,"tag":194,"props":2141,"children":2143},{"id":2142},"develop-locally-and-deploy",[2144],{"type":57,"value":2145},"Develop Locally and Deploy",{"type":48,"tag":92,"props":2147,"children":2149},{"className":94,"code":2148,"language":96,"meta":97,"style":97},"neon dev      # serves every function in neon.ts with hot reload; injects DATABASE_URL & friends\nneon deploy   # bundles with esbuild, uploads, and applies neon.ts to the linked branch\n",[2150],{"type":48,"tag":62,"props":2151,"children":2152},{"__ignoreMap":97},[2153,2170],{"type":48,"tag":103,"props":2154,"children":2155},{"class":105,"line":106},[2156,2160,2165],{"type":48,"tag":103,"props":2157,"children":2158},{"style":110},[2159],{"type":57,"value":8},{"type":48,"tag":103,"props":2161,"children":2162},{"style":116},[2163],{"type":57,"value":2164}," dev",{"type":48,"tag":103,"props":2166,"children":2167},{"style":627},[2168],{"type":57,"value":2169},"      # serves every function in neon.ts with hot reload; injects DATABASE_URL & friends\n",{"type":48,"tag":103,"props":2171,"children":2172},{"class":105,"line":633},[2173,2177,2182],{"type":48,"tag":103,"props":2174,"children":2175},{"style":110},[2176],{"type":57,"value":8},{"type":48,"tag":103,"props":2178,"children":2179},{"style":116},[2180],{"type":57,"value":2181}," deploy",{"type":48,"tag":103,"props":2183,"children":2184},{"style":627},[2185],{"type":57,"value":2186},"   # bundles with esbuild, uploads, and applies neon.ts to the linked branch\n",{"type":48,"tag":49,"props":2188,"children":2189},{},[2190,2192,2197,2199,2205,2206,2212,2214,2220,2221,2227,2229,2235,2237,2243,2245,2251,2253,2259,2261,2267],{"type":57,"value":2191},"To deploy a single function without ",{"type":48,"tag":62,"props":2193,"children":2195},{"className":2194},[],[2196],{"type":57,"value":177},{"type":57,"value":2198},": ",{"type":48,"tag":62,"props":2200,"children":2202},{"className":2201},[],[2203],{"type":57,"value":2204},"neon functions deploy \u003Cslug> --src src\u002Findex.ts",{"type":57,"value":1423},{"type":48,"tag":62,"props":2207,"children":2209},{"className":2208},[],[2210],{"type":57,"value":2211},"--src",{"type":57,"value":2213}," takes either the entry file or a directory containing ",{"type":48,"tag":62,"props":2215,"children":2217},{"className":2216},[],[2218],{"type":57,"value":2219},"index.ts",{"type":57,"value":431},{"type":48,"tag":62,"props":2222,"children":2224},{"className":2223},[],[2225],{"type":57,"value":2226},"index.mjs",{"type":57,"value":2228},", or ",{"type":48,"tag":62,"props":2230,"children":2232},{"className":2231},[],[2233],{"type":57,"value":2234},"index.js",{"type":57,"value":2236},"). Retrieve the public URL with ",{"type":48,"tag":62,"props":2238,"children":2240},{"className":2239},[],[2241],{"type":57,"value":2242},"neon functions get \u003Cslug>",{"type":57,"value":2244}," (the ",{"type":48,"tag":62,"props":2246,"children":2248},{"className":2247},[],[2249],{"type":57,"value":2250},"invocation_url",{"type":57,"value":2252}," field, of the form ",{"type":48,"tag":62,"props":2254,"children":2256},{"className":2255},[],[2257],{"type":57,"value":2258},"https:\u002F\u002F\u003Cbranch_id>-\u003Cslug>.compute.c-1.us-east-2.aws.neon.tech",{"type":57,"value":2260},"). Manage with ",{"type":48,"tag":62,"props":2262,"children":2264},{"className":2263},[],[2265],{"type":57,"value":2266},"neon functions list|get|delete",{"type":57,"value":158},{"type":48,"tag":49,"props":2269,"children":2270},{},[2271,2273,2279,2281,2286,2288,2293,2295,2301],{"type":57,"value":2272},"When ",{"type":48,"tag":62,"props":2274,"children":2276},{"className":2275},[],[2277],{"type":57,"value":2278},"neon checkout",{"type":57,"value":2280}," ",{"type":48,"tag":221,"props":2282,"children":2283},{},[2284],{"type":57,"value":2285},"creates",{"type":57,"value":2287}," a new branch and a ",{"type":48,"tag":62,"props":2289,"children":2291},{"className":2290},[],[2292],{"type":57,"value":177},{"type":57,"value":2294}," is present, it applies the policy automatically — deploying the function to the fresh branch. Checking out an existing branch does not re-deploy; run ",{"type":48,"tag":62,"props":2296,"children":2298},{"className":2297},[],[2299],{"type":57,"value":2300},"neon deploy",{"type":57,"value":2302}," explicitly.",{"type":48,"tag":194,"props":2304,"children":2306},{"id":2305},"neon-infrastructure-as-code-neonts",[2307,2309,2314],{"type":57,"value":2308},"Neon Infrastructure as Code (",{"type":48,"tag":62,"props":2310,"children":2312},{"className":2311},[],[2313],{"type":57,"value":177},{"type":57,"value":894},{"type":48,"tag":49,"props":2316,"children":2317},{},[2318,2320,2325,2327,2332,2334,2339,2341,2347,2349,2354,2356,2362,2364,2369],{"type":57,"value":2319},"The ",{"type":48,"tag":62,"props":2321,"children":2323},{"className":2322},[],[2324],{"type":57,"value":603},{"type":57,"value":2326}," block from ",{"type":48,"tag":82,"props":2328,"children":2330},{"href":2329},"#setup",[2331],{"type":57,"value":563},{"type":57,"value":2333}," is part of ",{"type":48,"tag":62,"props":2335,"children":2337},{"className":2336},[],[2338],{"type":57,"value":177},{"type":57,"value":2340},", Neon's infrastructure-as-code file — one TypeScript file declares every function (its ",{"type":48,"tag":62,"props":2342,"children":2344},{"className":2343},[],[2345],{"type":57,"value":2346},"source",{"type":57,"value":2348},", display ",{"type":48,"tag":62,"props":2350,"children":2352},{"className":2351},[],[2353],{"type":57,"value":909},{"type":57,"value":2355},", and ",{"type":48,"tag":62,"props":2357,"children":2359},{"className":2358},[],[2360],{"type":57,"value":2361},"env",{"type":57,"value":2363},") alongside any other branch services, in version control (see the ",{"type":48,"tag":62,"props":2365,"children":2367},{"className":2366},[],[2368],{"type":57,"value":8},{"type":57,"value":2370}," skill for the full reference). Treat it like Terraform for your branch:",{"type":48,"tag":92,"props":2372,"children":2374},{"className":94,"code":2373,"language":96,"meta":97,"style":97},"neon config status   # print the branch's live config (deployed functions)\nneon config plan     # dry-run diff of what apply would change\nneon config apply    # bundle + deploy the declared functions  (neon deploy is an alias)\n",[2375],{"type":48,"tag":62,"props":2376,"children":2377},{"__ignoreMap":97},[2378,2400,2421],{"type":48,"tag":103,"props":2379,"children":2380},{"class":105,"line":106},[2381,2385,2390,2395],{"type":48,"tag":103,"props":2382,"children":2383},{"style":110},[2384],{"type":57,"value":8},{"type":48,"tag":103,"props":2386,"children":2387},{"style":116},[2388],{"type":57,"value":2389}," config",{"type":48,"tag":103,"props":2391,"children":2392},{"style":116},[2393],{"type":57,"value":2394}," status",{"type":48,"tag":103,"props":2396,"children":2397},{"style":627},[2398],{"type":57,"value":2399},"   # print the branch's live config (deployed functions)\n",{"type":48,"tag":103,"props":2401,"children":2402},{"class":105,"line":633},[2403,2407,2411,2416],{"type":48,"tag":103,"props":2404,"children":2405},{"style":110},[2406],{"type":57,"value":8},{"type":48,"tag":103,"props":2408,"children":2409},{"style":116},[2410],{"type":57,"value":2389},{"type":48,"tag":103,"props":2412,"children":2413},{"style":116},[2414],{"type":57,"value":2415}," plan",{"type":48,"tag":103,"props":2417,"children":2418},{"style":627},[2419],{"type":57,"value":2420},"     # dry-run diff of what apply would change\n",{"type":48,"tag":103,"props":2422,"children":2423},{"class":105,"line":685},[2424,2428,2432,2437],{"type":48,"tag":103,"props":2425,"children":2426},{"style":110},[2427],{"type":57,"value":8},{"type":48,"tag":103,"props":2429,"children":2430},{"style":116},[2431],{"type":57,"value":2389},{"type":48,"tag":103,"props":2433,"children":2434},{"style":116},[2435],{"type":57,"value":2436}," apply",{"type":48,"tag":103,"props":2438,"children":2439},{"style":627},[2440],{"type":57,"value":2441},"    # bundle + deploy the declared functions  (neon deploy is an alias)\n",{"type":48,"tag":49,"props":2443,"children":2444},{},[2445,2447,2452,2454,2459,2461,2466,2468,2472,2474,2479,2481,2486],{"type":57,"value":2446},"Functions are ",{"type":48,"tag":53,"props":2448,"children":2449},{},[2450],{"type":57,"value":2451},"branch-scoped",{"type":57,"value":2453},": each branch runs its own deployment at its own URL. When a ",{"type":48,"tag":62,"props":2455,"children":2457},{"className":2456},[],[2458],{"type":57,"value":177},{"type":57,"value":2460}," is present, ",{"type":48,"tag":62,"props":2462,"children":2464},{"className":2463},[],[2465],{"type":57,"value":2278},{"type":57,"value":2467}," applies the policy as it ",{"type":48,"tag":221,"props":2469,"children":2470},{},[2471],{"type":57,"value":2285},{"type":57,"value":2473}," a branch, so a fresh preview\u002FCI branch comes up with the function already deployed. Checking out an ",{"type":48,"tag":221,"props":2475,"children":2476},{},[2477],{"type":57,"value":2478},"existing",{"type":57,"value":2480}," branch doesn't redeploy — run ",{"type":48,"tag":62,"props":2482,"children":2484},{"className":2483},[],[2485],{"type":57,"value":2300},{"type":57,"value":2487}," to apply changes.",{"type":48,"tag":49,"props":2489,"children":2490},{},[2491,2493,2499,2501,2507],{"type":57,"value":2492},"Per-branch deploy tuning (e.g. ",{"type":48,"tag":62,"props":2494,"children":2496},{"className":2495},[],[2497],{"type":57,"value":2498},"runtime",{"type":57,"value":2500},") lives in the ",{"type":48,"tag":62,"props":2502,"children":2504},{"className":2503},[],[2505],{"type":57,"value":2506},"branch",{"type":57,"value":2508}," closure, keyed by slug, so it can vary by branch without changing which functions exist:",{"type":48,"tag":92,"props":2510,"children":2512},{"className":615,"code":2511,"language":617,"meta":97,"style":97},"export default defineConfig({\n  preview: {\n    functions: { todos: { name: \"todo api\", source: \"src\u002Findex.ts\" } },\n  },\n  branch: (branch) => ({\n    preview: { functions: { todos: { runtime: \"nodejs24\" } } },\n  }),\n});\n",[2513],{"type":48,"tag":62,"props":2514,"children":2515},{"__ignoreMap":97},[2516,2539,2554,2636,2643,2679,2754,2771],{"type":48,"tag":103,"props":2517,"children":2518},{"class":105,"line":106},[2519,2523,2527,2531,2535],{"type":48,"tag":103,"props":2520,"children":2521},{"style":637},[2522],{"type":57,"value":701},{"type":48,"tag":103,"props":2524,"children":2525},{"style":637},[2526],{"type":57,"value":706},{"type":48,"tag":103,"props":2528,"children":2529},{"style":709},[2530],{"type":57,"value":652},{"type":48,"tag":103,"props":2532,"children":2533},{"style":649},[2534],{"type":57,"value":716},{"type":48,"tag":103,"props":2536,"children":2537},{"style":643},[2538],{"type":57,"value":721},{"type":48,"tag":103,"props":2540,"children":2541},{"class":105,"line":633},[2542,2546,2550],{"type":48,"tag":103,"props":2543,"children":2544},{"style":728},[2545],{"type":57,"value":731},{"type":48,"tag":103,"props":2547,"children":2548},{"style":643},[2549],{"type":57,"value":612},{"type":48,"tag":103,"props":2551,"children":2552},{"style":643},[2553],{"type":57,"value":740},{"type":48,"tag":103,"props":2555,"children":2556},{"class":105,"line":685},[2557,2561,2565,2569,2573,2577,2581,2586,2590,2594,2598,2602,2606,2611,2615,2619,2623,2627,2631],{"type":48,"tag":103,"props":2558,"children":2559},{"style":728},[2560],{"type":57,"value":749},{"type":48,"tag":103,"props":2562,"children":2563},{"style":643},[2564],{"type":57,"value":612},{"type":48,"tag":103,"props":2566,"children":2567},{"style":643},[2568],{"type":57,"value":646},{"type":48,"tag":103,"props":2570,"children":2571},{"style":728},[2572],{"type":57,"value":1150},{"type":48,"tag":103,"props":2574,"children":2575},{"style":643},[2576],{"type":57,"value":612},{"type":48,"tag":103,"props":2578,"children":2579},{"style":643},[2580],{"type":57,"value":646},{"type":48,"tag":103,"props":2582,"children":2583},{"style":728},[2584],{"type":57,"value":2585}," name",{"type":48,"tag":103,"props":2587,"children":2588},{"style":643},[2589],{"type":57,"value":612},{"type":48,"tag":103,"props":2591,"children":2592},{"style":643},[2593],{"type":57,"value":667},{"type":48,"tag":103,"props":2595,"children":2596},{"style":116},[2597],{"type":57,"value":805},{"type":48,"tag":103,"props":2599,"children":2600},{"style":643},[2601],{"type":57,"value":677},{"type":48,"tag":103,"props":2603,"children":2604},{"style":643},[2605],{"type":57,"value":814},{"type":48,"tag":103,"props":2607,"children":2608},{"style":728},[2609],{"type":57,"value":2610}," source",{"type":48,"tag":103,"props":2612,"children":2613},{"style":643},[2614],{"type":57,"value":612},{"type":48,"tag":103,"props":2616,"children":2617},{"style":643},[2618],{"type":57,"value":667},{"type":48,"tag":103,"props":2620,"children":2621},{"style":116},[2622],{"type":57,"value":841},{"type":48,"tag":103,"props":2624,"children":2625},{"style":643},[2626],{"type":57,"value":677},{"type":48,"tag":103,"props":2628,"children":2629},{"style":643},[2630],{"type":57,"value":657},{"type":48,"tag":103,"props":2632,"children":2633},{"style":643},[2634],{"type":57,"value":2635}," },\n",{"type":48,"tag":103,"props":2637,"children":2638},{"class":105,"line":695},[2639],{"type":48,"tag":103,"props":2640,"children":2641},{"style":643},[2642],{"type":57,"value":880},{"type":48,"tag":103,"props":2644,"children":2645},{"class":105,"line":724},[2646,2651,2655,2659,2663,2667,2671,2675],{"type":48,"tag":103,"props":2647,"children":2648},{"style":709},[2649],{"type":57,"value":2650},"  branch",{"type":48,"tag":103,"props":2652,"children":2653},{"style":643},[2654],{"type":57,"value":612},{"type":48,"tag":103,"props":2656,"children":2657},{"style":643},[2658],{"type":57,"value":1423},{"type":48,"tag":103,"props":2660,"children":2661},{"style":1426},[2662],{"type":57,"value":2506},{"type":48,"tag":103,"props":2664,"children":2665},{"style":643},[2666],{"type":57,"value":894},{"type":48,"tag":103,"props":2668,"children":2669},{"style":1188},[2670],{"type":57,"value":1438},{"type":48,"tag":103,"props":2672,"children":2673},{"style":649},[2674],{"type":57,"value":1423},{"type":48,"tag":103,"props":2676,"children":2677},{"style":643},[2678],{"type":57,"value":721},{"type":48,"tag":103,"props":2680,"children":2681},{"class":105,"line":743},[2682,2687,2691,2695,2700,2704,2708,2712,2716,2720,2725,2729,2733,2738,2742,2746,2750],{"type":48,"tag":103,"props":2683,"children":2684},{"style":728},[2685],{"type":57,"value":2686},"    preview",{"type":48,"tag":103,"props":2688,"children":2689},{"style":643},[2690],{"type":57,"value":612},{"type":48,"tag":103,"props":2692,"children":2693},{"style":643},[2694],{"type":57,"value":646},{"type":48,"tag":103,"props":2696,"children":2697},{"style":728},[2698],{"type":57,"value":2699}," functions",{"type":48,"tag":103,"props":2701,"children":2702},{"style":643},[2703],{"type":57,"value":612},{"type":48,"tag":103,"props":2705,"children":2706},{"style":643},[2707],{"type":57,"value":646},{"type":48,"tag":103,"props":2709,"children":2710},{"style":728},[2711],{"type":57,"value":1150},{"type":48,"tag":103,"props":2713,"children":2714},{"style":643},[2715],{"type":57,"value":612},{"type":48,"tag":103,"props":2717,"children":2718},{"style":643},[2719],{"type":57,"value":646},{"type":48,"tag":103,"props":2721,"children":2722},{"style":728},[2723],{"type":57,"value":2724}," runtime",{"type":48,"tag":103,"props":2726,"children":2727},{"style":643},[2728],{"type":57,"value":612},{"type":48,"tag":103,"props":2730,"children":2731},{"style":643},[2732],{"type":57,"value":667},{"type":48,"tag":103,"props":2734,"children":2735},{"style":116},[2736],{"type":57,"value":2737},"nodejs24",{"type":48,"tag":103,"props":2739,"children":2740},{"style":643},[2741],{"type":57,"value":677},{"type":48,"tag":103,"props":2743,"children":2744},{"style":643},[2745],{"type":57,"value":657},{"type":48,"tag":103,"props":2747,"children":2748},{"style":643},[2749],{"type":57,"value":657},{"type":48,"tag":103,"props":2751,"children":2752},{"style":643},[2753],{"type":57,"value":2635},{"type":48,"tag":103,"props":2755,"children":2756},{"class":105,"line":760},[2757,2762,2766],{"type":48,"tag":103,"props":2758,"children":2759},{"style":643},[2760],{"type":57,"value":2761},"  }",{"type":48,"tag":103,"props":2763,"children":2764},{"style":649},[2765],{"type":57,"value":894},{"type":48,"tag":103,"props":2767,"children":2768},{"style":643},[2769],{"type":57,"value":2770},",\n",{"type":48,"tag":103,"props":2772,"children":2773},{"class":105,"line":777},[2774,2778,2782],{"type":48,"tag":103,"props":2775,"children":2776},{"style":643},[2777],{"type":57,"value":889},{"type":48,"tag":103,"props":2779,"children":2780},{"style":649},[2781],{"type":57,"value":894},{"type":48,"tag":103,"props":2783,"children":2784},{"style":643},[2785],{"type":57,"value":682},{"type":48,"tag":194,"props":2787,"children":2789},{"id":2788},"environment-variables",[2790],{"type":57,"value":2791},"Environment Variables",{"type":48,"tag":49,"props":2793,"children":2794},{},[2795],{"type":57,"value":2796},"Neon injects branch-scoped connection strings and service URLs at runtime — you don't declare these or pass them at deploy time:",{"type":48,"tag":2798,"props":2799,"children":2800},"table",{},[2801,2820],{"type":48,"tag":2802,"props":2803,"children":2804},"thead",{},[2805],{"type":48,"tag":2806,"props":2807,"children":2808},"tr",{},[2809,2815],{"type":48,"tag":2810,"props":2811,"children":2812},"th",{},[2813],{"type":57,"value":2814},"Variable",{"type":48,"tag":2810,"props":2816,"children":2817},{},[2818],{"type":57,"value":2819},"Notes",{"type":48,"tag":2821,"props":2822,"children":2823},"tbody",{},[2824,2863,2879,2911,2928],{"type":48,"tag":2806,"props":2825,"children":2826},{},[2827,2837],{"type":48,"tag":2828,"props":2829,"children":2830},"td",{},[2831],{"type":48,"tag":62,"props":2832,"children":2834},{"className":2833},[],[2835],{"type":57,"value":2836},"NEON_BRANCH",{"type":48,"tag":2828,"props":2838,"children":2839},{},[2840,2842,2846,2848,2854,2855,2861],{"type":57,"value":2841},"The branch ",{"type":48,"tag":53,"props":2843,"children":2844},{},[2845],{"type":57,"value":909},{"type":57,"value":2847}," (e.g. ",{"type":48,"tag":62,"props":2849,"children":2851},{"className":2850},[],[2852],{"type":57,"value":2853},"main",{"type":57,"value":431},{"type":48,"tag":62,"props":2856,"children":2858},{"className":2857},[],[2859],{"type":57,"value":2860},"preview\u002Ffoo",{"type":57,"value":2862},"). Injected on every branch, including the default.",{"type":48,"tag":2806,"props":2864,"children":2865},{},[2866,2874],{"type":48,"tag":2828,"props":2867,"children":2868},{},[2869],{"type":48,"tag":62,"props":2870,"children":2872},{"className":2871},[],[2873],{"type":57,"value":169},{"type":48,"tag":2828,"props":2875,"children":2876},{},[2877],{"type":57,"value":2878},"Pooled connection string. Use for most queries. Present only if the branch has Postgres.",{"type":48,"tag":2806,"props":2880,"children":2881},{},[2882,2891],{"type":48,"tag":2828,"props":2883,"children":2884},{},[2885],{"type":48,"tag":62,"props":2886,"children":2888},{"className":2887},[],[2889],{"type":57,"value":2890},"DATABASE_URL_UNPOOLED",{"type":48,"tag":2828,"props":2892,"children":2893},{},[2894,2896,2902,2903,2909],{"type":57,"value":2895},"Direct connection. Use for migrations, ",{"type":48,"tag":62,"props":2897,"children":2899},{"className":2898},[],[2900],{"type":57,"value":2901},"LISTEN",{"type":57,"value":1410},{"type":48,"tag":62,"props":2904,"children":2906},{"className":2905},[],[2907],{"type":57,"value":2908},"NOTIFY",{"type":57,"value":2910},", multi-round-trip transactions.",{"type":48,"tag":2806,"props":2912,"children":2913},{},[2914,2923],{"type":48,"tag":2828,"props":2915,"children":2916},{},[2917],{"type":48,"tag":62,"props":2918,"children":2920},{"className":2919},[],[2921],{"type":57,"value":2922},"NEON_AUTH_BASE_URL",{"type":48,"tag":2828,"props":2924,"children":2925},{},[2926],{"type":57,"value":2927},"Present when Neon Auth is enabled on the branch.",{"type":48,"tag":2806,"props":2929,"children":2930},{},[2931,2940],{"type":48,"tag":2828,"props":2932,"children":2933},{},[2934],{"type":48,"tag":62,"props":2935,"children":2937},{"className":2936},[],[2938],{"type":57,"value":2939},"NEON_DATA_API_URL",{"type":48,"tag":2828,"props":2941,"children":2942},{},[2943],{"type":57,"value":2944},"Present when the Data API is enabled on the branch.",{"type":48,"tag":49,"props":2946,"children":2947},{},[2948,2950,2956,2958,2964,2966,2972,2973,2979],{"type":57,"value":2949},"Object storage (",{"type":48,"tag":62,"props":2951,"children":2953},{"className":2952},[],[2954],{"type":57,"value":2955},"AWS_*",{"type":57,"value":2957},") and AI Gateway (",{"type":48,"tag":62,"props":2959,"children":2961},{"className":2960},[],[2962],{"type":57,"value":2963},"NEON_AI_GATEWAY_*",{"type":57,"value":2965},") vars are also injected when those services are declared — see the ",{"type":48,"tag":62,"props":2967,"children":2969},{"className":2968},[],[2970],{"type":57,"value":2971},"neon-object-storage",{"type":57,"value":310},{"type":48,"tag":62,"props":2974,"children":2976},{"className":2975},[],[2977],{"type":57,"value":2978},"neon-ai-gateway",{"type":57,"value":2980}," skills.",{"type":48,"tag":49,"props":2982,"children":2983},{},[2984,2990,2992,2998,2999,3004,3006,3011],{"type":48,"tag":62,"props":2985,"children":2987},{"className":2986},[],[2988],{"type":57,"value":2989},"neon env pull",{"type":57,"value":2991}," \u002F ",{"type":48,"tag":62,"props":2993,"children":2995},{"className":2994},[],[2996],{"type":57,"value":2997},"neon-env run",{"type":57,"value":2991},{"type":48,"tag":62,"props":3000,"children":3002},{"className":3001},[],[3003],{"type":57,"value":190},{"type":57,"value":3005}," emit ",{"type":48,"tag":62,"props":3007,"children":3009},{"className":3008},[],[3010],{"type":57,"value":2836},{"type":57,"value":3012}," (and the connection strings) into your local dev environment too, so local runs mirror the deployed runtime.",{"type":48,"tag":49,"props":3014,"children":3015},{},[3016,3021,3023,3029,3031,3037,3039,3045,3047,3052,3054,3059,3061,3067],{"type":48,"tag":53,"props":3017,"children":3018},{},[3019],{"type":57,"value":3020},"Your own secrets",{"type":57,"value":3022}," are per-deployment. Set them with ",{"type":48,"tag":62,"props":3024,"children":3026},{"className":3025},[],[3027],{"type":57,"value":3028},"--env KEY=VALUE",{"type":57,"value":3030}," on ",{"type":48,"tag":62,"props":3032,"children":3034},{"className":3033},[],[3035],{"type":57,"value":3036},"neon functions deploy",{"type":57,"value":3038}," (repeatable; ",{"type":48,"tag":62,"props":3040,"children":3042},{"className":3041},[],[3043],{"type":57,"value":3044},"--env KEY=",{"type":57,"value":3046}," deletes a key, unmentioned keys carry over), or declare them in ",{"type":48,"tag":62,"props":3048,"children":3050},{"className":3049},[],[3051],{"type":57,"value":177},{"type":57,"value":3053}," under the function's ",{"type":48,"tag":62,"props":3055,"children":3057},{"className":3056},[],[3058],{"type":57,"value":2361},{"type":57,"value":3060}," (resolved at deploy time, so read from ",{"type":48,"tag":62,"props":3062,"children":3064},{"className":3063},[],[3065],{"type":57,"value":3066},"process.env",{"type":57,"value":3068}," to avoid hardcoding):",{"type":48,"tag":92,"props":3070,"children":3072},{"className":615,"code":3071,"language":617,"meta":97,"style":97},"functions: {\n  todos: {\n    name: \"todo api\",\n    source: \"src\u002Findex.ts\",\n    env: { RESEND_API_KEY: process.env.RESEND_API_KEY! },\n  },\n}\n",[3073],{"type":48,"tag":62,"props":3074,"children":3075},{"__ignoreMap":97},[3076,3092,3108,3136,3164,3220,3227],{"type":48,"tag":103,"props":3077,"children":3078},{"class":105,"line":106},[3079,3084,3088],{"type":48,"tag":103,"props":3080,"children":3081},{"style":110},[3082],{"type":57,"value":3083},"functions",{"type":48,"tag":103,"props":3085,"children":3086},{"style":643},[3087],{"type":57,"value":612},{"type":48,"tag":103,"props":3089,"children":3090},{"style":643},[3091],{"type":57,"value":740},{"type":48,"tag":103,"props":3093,"children":3094},{"class":105,"line":633},[3095,3100,3104],{"type":48,"tag":103,"props":3096,"children":3097},{"style":110},[3098],{"type":57,"value":3099},"  todos",{"type":48,"tag":103,"props":3101,"children":3102},{"style":643},[3103],{"type":57,"value":612},{"type":48,"tag":103,"props":3105,"children":3106},{"style":643},[3107],{"type":57,"value":740},{"type":48,"tag":103,"props":3109,"children":3110},{"class":105,"line":685},[3111,3116,3120,3124,3128,3132],{"type":48,"tag":103,"props":3112,"children":3113},{"style":110},[3114],{"type":57,"value":3115},"    name",{"type":48,"tag":103,"props":3117,"children":3118},{"style":643},[3119],{"type":57,"value":612},{"type":48,"tag":103,"props":3121,"children":3122},{"style":643},[3123],{"type":57,"value":667},{"type":48,"tag":103,"props":3125,"children":3126},{"style":116},[3127],{"type":57,"value":805},{"type":48,"tag":103,"props":3129,"children":3130},{"style":643},[3131],{"type":57,"value":677},{"type":48,"tag":103,"props":3133,"children":3134},{"style":643},[3135],{"type":57,"value":2770},{"type":48,"tag":103,"props":3137,"children":3138},{"class":105,"line":695},[3139,3144,3148,3152,3156,3160],{"type":48,"tag":103,"props":3140,"children":3141},{"style":110},[3142],{"type":57,"value":3143},"    source",{"type":48,"tag":103,"props":3145,"children":3146},{"style":643},[3147],{"type":57,"value":612},{"type":48,"tag":103,"props":3149,"children":3150},{"style":643},[3151],{"type":57,"value":667},{"type":48,"tag":103,"props":3153,"children":3154},{"style":116},[3155],{"type":57,"value":841},{"type":48,"tag":103,"props":3157,"children":3158},{"style":643},[3159],{"type":57,"value":677},{"type":48,"tag":103,"props":3161,"children":3162},{"style":643},[3163],{"type":57,"value":2770},{"type":48,"tag":103,"props":3165,"children":3166},{"class":105,"line":724},[3167,3172,3176,3180,3185,3189,3194,3198,3202,3206,3211,3216],{"type":48,"tag":103,"props":3168,"children":3169},{"style":110},[3170],{"type":57,"value":3171},"    env",{"type":48,"tag":103,"props":3173,"children":3174},{"style":643},[3175],{"type":57,"value":612},{"type":48,"tag":103,"props":3177,"children":3178},{"style":643},[3179],{"type":57,"value":646},{"type":48,"tag":103,"props":3181,"children":3182},{"style":110},[3183],{"type":57,"value":3184}," RESEND_API_KEY",{"type":48,"tag":103,"props":3186,"children":3187},{"style":643},[3188],{"type":57,"value":612},{"type":48,"tag":103,"props":3190,"children":3191},{"style":649},[3192],{"type":57,"value":3193}," process",{"type":48,"tag":103,"props":3195,"children":3196},{"style":643},[3197],{"type":57,"value":158},{"type":48,"tag":103,"props":3199,"children":3200},{"style":649},[3201],{"type":57,"value":2361},{"type":48,"tag":103,"props":3203,"children":3204},{"style":643},[3205],{"type":57,"value":158},{"type":48,"tag":103,"props":3207,"children":3208},{"style":649},[3209],{"type":57,"value":3210},"RESEND_API_KEY",{"type":48,"tag":103,"props":3212,"children":3213},{"style":643},[3214],{"type":57,"value":3215},"!",{"type":48,"tag":103,"props":3217,"children":3218},{"style":643},[3219],{"type":57,"value":2635},{"type":48,"tag":103,"props":3221,"children":3222},{"class":105,"line":743},[3223],{"type":48,"tag":103,"props":3224,"children":3225},{"style":643},[3226],{"type":57,"value":880},{"type":48,"tag":103,"props":3228,"children":3229},{"class":105,"line":760},[3230],{"type":48,"tag":103,"props":3231,"children":3232},{"style":643},[3233],{"type":57,"value":3234},"}\n",{"type":48,"tag":49,"props":3236,"children":3237},{},[3238,3240,3246,3248,3254,3256,3261,3262,3268,3269,3275,3277,3283,3285,3291,3293,3299],{"type":57,"value":3239},"Load a ",{"type":48,"tag":62,"props":3241,"children":3243},{"className":3242},[],[3244],{"type":57,"value":3245},".env",{"type":57,"value":3247}," before deploy with ",{"type":48,"tag":62,"props":3249,"children":3251},{"className":3250},[],[3252],{"type":57,"value":3253},"neon deploy --env .env.production",{"type":57,"value":3255},". Pull the branch's Neon-managed vars onto disk for local dev with ",{"type":48,"tag":62,"props":3257,"children":3259},{"className":3258},[],[3260],{"type":57,"value":2989},{"type":57,"value":1423},{"type":48,"tag":62,"props":3263,"children":3265},{"className":3264},[],[3266],{"type":57,"value":3267},"link",{"type":57,"value":1410},{"type":48,"tag":62,"props":3270,"children":3272},{"className":3271},[],[3273],{"type":57,"value":3274},"checkout",{"type":57,"value":3276}," do this automatically; pass ",{"type":48,"tag":62,"props":3278,"children":3280},{"className":3279},[],[3281],{"type":57,"value":3282},"--no-env-pull",{"type":57,"value":3284}," to skip and use ",{"type":48,"tag":62,"props":3286,"children":3288},{"className":3287},[],[3289],{"type":57,"value":3290},"neon-env run -- \u003Ccmd>",{"type":57,"value":3292}," for runtime injection). Limits: ≤1,000 vars, ≤64 KiB total, and the ",{"type":48,"tag":62,"props":3294,"children":3296},{"className":3295},[],[3297],{"type":57,"value":3298},"NEON_",{"type":57,"value":3300}," prefix is reserved.",{"type":48,"tag":194,"props":3302,"children":3304},{"id":3303},"connecting-to-postgres",[3305],{"type":57,"value":3306},"Connecting to Postgres",{"type":48,"tag":49,"props":3308,"children":3309},{},[3310,3312,3317],{"type":57,"value":3311},"When the branch has Postgres, Neon ",{"type":48,"tag":53,"props":3313,"children":3314},{},[3315],{"type":57,"value":3316},"injects the connection strings at runtime",{"type":57,"value":3318}," — you don't declare them, pass them at deploy time, or hardcode anything. The two you'll use:",{"type":48,"tag":206,"props":3320,"children":3321},{},[3322,3346],{"type":48,"tag":210,"props":3323,"children":3324},{},[3325,3330,3332,3337,3339,3344],{"type":48,"tag":62,"props":3326,"children":3328},{"className":3327},[],[3329],{"type":57,"value":169},{"type":57,"value":3331}," — ",{"type":48,"tag":53,"props":3333,"children":3334},{},[3335],{"type":57,"value":3336},"pooled",{"type":57,"value":3338}," connection string (routed through Neon's connection pooler). Use it for normal request\u002Fresponse query traffic. Kept un-prefixed because every Postgres ORM (Drizzle, Prisma, Knex, …) reads ",{"type":48,"tag":62,"props":3340,"children":3342},{"className":3341},[],[3343],{"type":57,"value":169},{"type":57,"value":3345}," by default.",{"type":48,"tag":210,"props":3347,"children":3348},{},[3349,3354,3355,3360,3362,3367,3368,3373],{"type":48,"tag":62,"props":3350,"children":3352},{"className":3351},[],[3353],{"type":57,"value":2890},{"type":57,"value":3331},{"type":48,"tag":53,"props":3356,"children":3357},{},[3358],{"type":57,"value":3359},"direct",{"type":57,"value":3361}," connection string to the same database. Use it for migrations, ",{"type":48,"tag":62,"props":3363,"children":3365},{"className":3364},[],[3366],{"type":57,"value":2901},{"type":57,"value":1410},{"type":48,"tag":62,"props":3369,"children":3371},{"className":3370},[],[3372],{"type":57,"value":2908},{"type":57,"value":3374},", and long multi-statement transactions.",{"type":48,"tag":49,"props":3376,"children":3377},{},[3378,3389,3391,3396],{"type":48,"tag":53,"props":3379,"children":3380},{},[3381,3383,3388],{"type":57,"value":3382},"Use Drizzle (or another ORM) on top of node-postgres (",{"type":48,"tag":62,"props":3384,"children":3386},{"className":3385},[],[3387],{"type":57,"value":243},{"type":57,"value":894},{"type":57,"value":3390}," for queries and schema management — not Neon's serverless driver. Functions are long-running and reuse an isolate across many requests, so a persistent ",{"type":48,"tag":62,"props":3392,"children":3394},{"className":3393},[],[3395],{"type":57,"value":243},{"type":57,"value":3397}," pool is the right fit; the serverless driver's HTTP transport is meant for fully isolated, lambda-style runtimes.",{"type":48,"tag":49,"props":3399,"children":3400},{},[3401,3403,3408],{"type":57,"value":3402},"Create the connection pool ",{"type":48,"tag":53,"props":3404,"children":3405},{},[3406],{"type":57,"value":3407},"once at module scope",{"type":57,"value":3409}," and reuse it across requests — don't open a connection per request:",{"type":48,"tag":92,"props":3411,"children":3413},{"className":615,"code":3412,"language":617,"meta":97,"style":97},"import { drizzle } from \"drizzle-orm\u002Fnode-postgres\";\nimport { Pool } from \"pg\";\n\n\u002F\u002F Created once per isolate; reused by every request that isolate handles.\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 5 });\nconst db = drizzle(pool);\n",[3414],{"type":48,"tag":62,"props":3415,"children":3416},{"__ignoreMap":97},[3417,3456,3495,3502,3510,3597],{"type":48,"tag":103,"props":3418,"children":3419},{"class":105,"line":106},[3420,3424,3428,3432,3436,3440,3444,3448,3452],{"type":48,"tag":103,"props":3421,"children":3422},{"style":637},[3423],{"type":57,"value":640},{"type":48,"tag":103,"props":3425,"children":3426},{"style":643},[3427],{"type":57,"value":646},{"type":48,"tag":103,"props":3429,"children":3430},{"style":649},[3431],{"type":57,"value":994},{"type":48,"tag":103,"props":3433,"children":3434},{"style":643},[3435],{"type":57,"value":657},{"type":48,"tag":103,"props":3437,"children":3438},{"style":637},[3439],{"type":57,"value":662},{"type":48,"tag":103,"props":3441,"children":3442},{"style":643},[3443],{"type":57,"value":667},{"type":48,"tag":103,"props":3445,"children":3446},{"style":116},[3447],{"type":57,"value":1011},{"type":48,"tag":103,"props":3449,"children":3450},{"style":643},[3451],{"type":57,"value":677},{"type":48,"tag":103,"props":3453,"children":3454},{"style":643},[3455],{"type":57,"value":682},{"type":48,"tag":103,"props":3457,"children":3458},{"class":105,"line":633},[3459,3463,3467,3471,3475,3479,3483,3487,3491],{"type":48,"tag":103,"props":3460,"children":3461},{"style":637},[3462],{"type":57,"value":640},{"type":48,"tag":103,"props":3464,"children":3465},{"style":643},[3466],{"type":57,"value":646},{"type":48,"tag":103,"props":3468,"children":3469},{"style":649},[3470],{"type":57,"value":1035},{"type":48,"tag":103,"props":3472,"children":3473},{"style":643},[3474],{"type":57,"value":657},{"type":48,"tag":103,"props":3476,"children":3477},{"style":637},[3478],{"type":57,"value":662},{"type":48,"tag":103,"props":3480,"children":3481},{"style":643},[3482],{"type":57,"value":667},{"type":48,"tag":103,"props":3484,"children":3485},{"style":116},[3486],{"type":57,"value":243},{"type":48,"tag":103,"props":3488,"children":3489},{"style":643},[3490],{"type":57,"value":677},{"type":48,"tag":103,"props":3492,"children":3493},{"style":643},[3494],{"type":57,"value":682},{"type":48,"tag":103,"props":3496,"children":3497},{"class":105,"line":685},[3498],{"type":48,"tag":103,"props":3499,"children":3500},{"emptyLinePlaceholder":689},[3501],{"type":57,"value":692},{"type":48,"tag":103,"props":3503,"children":3504},{"class":105,"line":695},[3505],{"type":48,"tag":103,"props":3506,"children":3507},{"style":627},[3508],{"type":57,"value":3509},"\u002F\u002F Created once per isolate; reused by every request that isolate handles.\n",{"type":48,"tag":103,"props":3511,"children":3512},{"class":105,"line":724},[3513,3517,3521,3525,3529,3533,3537,3541,3545,3549,3553,3557,3561,3565,3569,3573,3577,3581,3585,3589,3593],{"type":48,"tag":103,"props":3514,"children":3515},{"style":1188},[3516],{"type":57,"value":1191},{"type":48,"tag":103,"props":3518,"children":3519},{"style":649},[3520],{"type":57,"value":1226},{"type":48,"tag":103,"props":3522,"children":3523},{"style":643},[3524],{"type":57,"value":1201},{"type":48,"tag":103,"props":3526,"children":3527},{"style":643},[3528],{"type":57,"value":1235},{"type":48,"tag":103,"props":3530,"children":3531},{"style":709},[3532],{"type":57,"value":1035},{"type":48,"tag":103,"props":3534,"children":3535},{"style":649},[3536],{"type":57,"value":716},{"type":48,"tag":103,"props":3538,"children":3539},{"style":643},[3540],{"type":57,"value":1248},{"type":48,"tag":103,"props":3542,"children":3543},{"style":728},[3544],{"type":57,"value":1253},{"type":48,"tag":103,"props":3546,"children":3547},{"style":643},[3548],{"type":57,"value":612},{"type":48,"tag":103,"props":3550,"children":3551},{"style":649},[3552],{"type":57,"value":3193},{"type":48,"tag":103,"props":3554,"children":3555},{"style":643},[3556],{"type":57,"value":158},{"type":48,"tag":103,"props":3558,"children":3559},{"style":649},[3560],{"type":57,"value":2361},{"type":48,"tag":103,"props":3562,"children":3563},{"style":643},[3564],{"type":57,"value":158},{"type":48,"tag":103,"props":3566,"children":3567},{"style":649},[3568],{"type":57,"value":169},{"type":48,"tag":103,"props":3570,"children":3571},{"style":643},[3572],{"type":57,"value":814},{"type":48,"tag":103,"props":3574,"children":3575},{"style":728},[3576],{"type":57,"value":1289},{"type":48,"tag":103,"props":3578,"children":3579},{"style":643},[3580],{"type":57,"value":612},{"type":48,"tag":103,"props":3582,"children":3583},{"style":1296},[3584],{"type":57,"value":1299},{"type":48,"tag":103,"props":3586,"children":3587},{"style":643},[3588],{"type":57,"value":657},{"type":48,"tag":103,"props":3590,"children":3591},{"style":649},[3592],{"type":57,"value":894},{"type":48,"tag":103,"props":3594,"children":3595},{"style":643},[3596],{"type":57,"value":682},{"type":48,"tag":103,"props":3598,"children":3599},{"class":105,"line":743},[3600,3604,3608,3612,3616,3620],{"type":48,"tag":103,"props":3601,"children":3602},{"style":1188},[3603],{"type":57,"value":1191},{"type":48,"tag":103,"props":3605,"children":3606},{"style":649},[3607],{"type":57,"value":1323},{"type":48,"tag":103,"props":3609,"children":3610},{"style":643},[3611],{"type":57,"value":1201},{"type":48,"tag":103,"props":3613,"children":3614},{"style":709},[3615],{"type":57,"value":994},{"type":48,"tag":103,"props":3617,"children":3618},{"style":649},[3619],{"type":57,"value":1336},{"type":48,"tag":103,"props":3621,"children":3622},{"style":643},[3623],{"type":57,"value":682},{"type":48,"tag":49,"props":3625,"children":3626},{},[3627,3632,3634,3638],{"type":48,"tag":53,"props":3628,"children":3629},{},[3630],{"type":57,"value":3631},"Pooling is recommended because an isolate is reused across many requests",{"type":57,"value":3633}," (and several requests can be in flight on the same isolate at once — see ",{"type":48,"tag":82,"props":3635,"children":3636},{"href":305},[3637],{"type":57,"value":308},{"type":57,"value":3639},"). A module-scope pool is opened once on cold start and then shared by every subsequent request that isolate serves, so you amortize connection setup instead of paying it on every request and you avoid exhausting Postgres connections under load.",{"type":48,"tag":49,"props":3641,"children":3642},{},[3643,3645,3650,3652,3658,3660,3666,3667,3673],{"type":57,"value":3644},"Keep ",{"type":48,"tag":62,"props":3646,"children":3648},{"className":3647},[],[3649],{"type":57,"value":1949},{"type":57,"value":3651}," small (e.g. ",{"type":48,"tag":62,"props":3653,"children":3655},{"className":3654},[],[3656],{"type":57,"value":3657},"5",{"type":57,"value":3659},"): each isolate keeps its own pool, so total connections to Postgres scale with the number of live isolates. You don't need to close the pool on shutdown — when the runtime evicts an isolate it sends ",{"type":48,"tag":62,"props":3661,"children":3663},{"className":3662},[],[3664],{"type":57,"value":3665},"SIGINT",{"type":57,"value":1410},{"type":48,"tag":62,"props":3668,"children":3670},{"className":3669},[],[3671],{"type":57,"value":3672},"SIGTERM",{"type":57,"value":3674},", and Neon's pooler reclaims those connections for you, so an explicit drain handler is redundant.",{"type":48,"tag":3676,"props":3677,"children":3678},"blockquote",{},[3679],{"type":48,"tag":49,"props":3680,"children":3681},{},[3682,3684,3690,3692,3696,3698,3703,3705,3710],{"type":57,"value":3683},"Reading ",{"type":48,"tag":62,"props":3685,"children":3687},{"className":3686},[],[3688],{"type":57,"value":3689},"process.env.DATABASE_URL",{"type":57,"value":3691}," directly works everywhere. The function in ",{"type":48,"tag":82,"props":3693,"children":3694},{"href":2329},[3695],{"type":57,"value":563},{"type":57,"value":3697}," instead uses ",{"type":48,"tag":62,"props":3699,"children":3701},{"className":3700},[],[3702],{"type":57,"value":1092},{"type":57,"value":3704},"'s ",{"type":48,"tag":62,"props":3706,"children":3708},{"className":3707},[],[3709],{"type":57,"value":1960},{"type":57,"value":3711}," to read the same value in a typed, validated way — either is fine.",{"type":48,"tag":194,"props":3713,"children":3715},{"id":3714},"timeouts-and-runtime-limits",[3716],{"type":57,"value":308},{"type":48,"tag":49,"props":3718,"children":3719},{},[3720,3722,3727],{"type":57,"value":3721},"Functions are long-running but ",{"type":48,"tag":53,"props":3723,"children":3724},{},[3725],{"type":57,"value":3726},"still serverless",{"type":57,"value":3728}," — they are a request\u002Fresponse runtime, not a background job runner. The hard limits:",{"type":48,"tag":206,"props":3730,"children":3731},{},[3732,3749,3759,3803,3828],{"type":48,"tag":210,"props":3733,"children":3734},{},[3735,3740,3742,3747],{"type":48,"tag":53,"props":3736,"children":3737},{},[3738],{"type":57,"value":3739},"Time to first byte: 15 minutes.",{"type":57,"value":3741}," Your handler must ",{"type":48,"tag":221,"props":3743,"children":3744},{},[3745],{"type":57,"value":3746},"begin",{"type":57,"value":3748}," returning a response within 15 minutes of receiving a request. Most handlers finish in seconds; the 15-minute ceiling exists so agent workloads like image\u002Fvideo generation have room.",{"type":48,"tag":210,"props":3750,"children":3751},{},[3752,3757],{"type":48,"tag":53,"props":3753,"children":3754},{},[3755],{"type":57,"value":3756},"Heartbeat: 15 minutes.",{"type":57,"value":3758}," Open WebSocket\u002FSSE connections stay alive as long as data flows. The timeout only fires when a connection goes silent — send at least one byte every 15 minutes to keep a quiet stream alive.",{"type":48,"tag":210,"props":3760,"children":3761},{},[3762,3772,3774,3779,3781,3786,3788,3793,3795,3801],{"type":48,"tag":53,"props":3763,"children":3764},{},[3765,3770],{"type":48,"tag":62,"props":3766,"children":3768},{"className":3767},[],[3769],{"type":57,"value":288},{"type":57,"value":3771},": 15 minutes.",{"type":57,"value":3773}," Work registered with ",{"type":48,"tag":62,"props":3775,"children":3777},{"className":3776},[],[3778],{"type":57,"value":288},{"type":57,"value":3780}," keeps the invocation alive after the response is sent, up to 15 minutes — for cleanup like analytics writes and audit logs, ",{"type":48,"tag":53,"props":3782,"children":3783},{},[3784],{"type":57,"value":3785},"not",{"type":57,"value":3787}," a background job runner. (",{"type":48,"tag":62,"props":3789,"children":3791},{"className":3790},[],[3792],{"type":57,"value":288},{"type":57,"value":3794}," from ",{"type":48,"tag":62,"props":3796,"children":3798},{"className":3797},[],[3799],{"type":57,"value":3800},"@neon\u002Ffunctions",{"type":57,"value":3802}," is currently a stub during the preview.)",{"type":48,"tag":210,"props":3804,"children":3805},{},[3806,3811,3813,3818,3820,3826],{"type":48,"tag":53,"props":3807,"children":3808},{},[3809],{"type":57,"value":3810},"Idle eviction.",{"type":57,"value":3812}," With no active connections the platform shuts the function down; it may also evict\u002Frestart for operational reasons — e.g. maintenance, or moving the function to a different compute node (active functions can run for hours first). Treat eviction like a process restart — WebSocket\u002FSSE clients must reconnect. The platform sends ",{"type":48,"tag":62,"props":3814,"children":3816},{"className":3815},[],[3817],{"type":57,"value":3665},{"type":57,"value":3819}," before evicting, so a ",{"type":48,"tag":62,"props":3821,"children":3823},{"className":3822},[],[3824],{"type":57,"value":3825},"process.on(\"SIGINT\", ...)",{"type":57,"value":3827}," handler lets you detect that the function is about to be evicted and run any last-minute cleanup. You don't need one just to close Postgres connections — Neon's pooler reclaims those on its own.",{"type":48,"tag":210,"props":3829,"children":3830},{},[3831,3836,3838,3844,3846,3851,3853,3858],{"type":48,"tag":53,"props":3832,"children":3833},{},[3834],{"type":57,"value":3835},"Runtime:",{"type":57,"value":3837}," Node.js 24, memory fixed at 2048 MiB during the preview. Slugs must match ",{"type":48,"tag":62,"props":3839,"children":3841},{"className":3840},[],[3842],{"type":57,"value":3843},"^[a-z0-9]{1,20}$",{"type":57,"value":3845},". ",{"type":48,"tag":53,"props":3847,"children":3848},{},[3849],{"type":57,"value":3850},"An isolate is reused across many requests",{"type":57,"value":3852}," — multiple requests can be in flight on the same isolate at once (interleaved on Node's single-threaded event loop), and under load the runtime runs several isolates in parallel, each with its own copy of module state. State held in module scope is therefore per-isolate (shared by every request that isolate handles) and in-memory only — persist anything that must survive eviction in Postgres. This reuse is exactly why you create a connection pool once at module scope rather than per request (see ",{"type":48,"tag":82,"props":3854,"children":3856},{"href":3855},"#connecting-to-postgres",[3857],{"type":57,"value":3306},{"type":57,"value":318},{"type":48,"tag":194,"props":3860,"children":3862},{"id":3861},"functions-as-an-agent-backend-nextjs-and-similar-frameworks",[3863],{"type":57,"value":3864},"Functions as an Agent Backend (Next.js and Similar Frameworks)",{"type":48,"tag":49,"props":3866,"children":3867},{},[3868,3870,3875,3877,3881,3883,3888],{"type":57,"value":3869},"A Neon Function is a great home for an AI agent precisely because it ",{"type":48,"tag":53,"props":3871,"children":3872},{},[3873],{"type":57,"value":3874},"doesn't time out",{"type":57,"value":3876}," the way lambda-style serverless does (15-minute budget, see ",{"type":48,"tag":82,"props":3878,"children":3879},{"href":305},[3880],{"type":57,"value":308},{"type":57,"value":3882},"). But that advantage disappears the moment you ",{"type":48,"tag":53,"props":3884,"children":3885},{},[3886],{"type":57,"value":3887},"proxy the agent stream through your web app's backend",{"type":57,"value":3889}," — a Next.js route handler, Remix\u002FSvelteKit\u002FNuxt action, etc. hosted on Vercel, Netlify, Cloudflare, and the like. Those platforms cap serverless\u002Fedge execution at short windows (often ~10–60s, sometimes up to ~300s), so a long agent or image\u002Fvideo generation stream gets cut off mid-response even though the Neon Function would happily keep going.",{"type":48,"tag":49,"props":3891,"children":3892},{},[3893,3898,3900,3907,3908,3915,3917,3922,3924,3930,3932,3939,3941,3948],{"type":48,"tag":53,"props":3894,"children":3895},{},[3896],{"type":57,"value":3897},"Building the agent itself.",{"type":57,"value":3899}," The ",{"type":48,"tag":82,"props":3901,"children":3904},{"href":3902,"rel":3903},"https:\u002F\u002Fai-sdk.dev",[86],[3905],{"type":57,"value":3906},"Vercel AI SDK",{"type":57,"value":310},{"type":48,"tag":82,"props":3909,"children":3912},{"href":3910,"rel":3911},"https:\u002F\u002Fmastra.ai",[86],[3913],{"type":57,"value":3914},"Mastra",{"type":57,"value":3916}," are the recommended ways to build the agent — point either at the Neon AI Gateway (see the ",{"type":48,"tag":62,"props":3918,"children":3920},{"className":3919},[],[3921],{"type":57,"value":2978},{"type":57,"value":3923}," skill) for one credential across every model, with no extra provider keys. For a complete AI SDK agent running as a Function (streaming ",{"type":48,"tag":62,"props":3925,"children":3927},{"className":3926},[],[3928],{"type":57,"value":3929},"toUIMessageStreamResponse",{"type":57,"value":3931},", multi-step tool calling next to Postgres, and persisting generated images to Object Storage), see ",{"type":48,"tag":82,"props":3933,"children":3936},{"href":3934,"rel":3935},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fai-sdk.md",[86],[3937],{"type":57,"value":3938},"references\u002Fai-sdk.md",{"type":57,"value":3940},"; for the Mastra equivalent with built-in tracing, see ",{"type":48,"tag":82,"props":3942,"children":3945},{"href":3943,"rel":3944},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fmastra-studio.md",[86],[3946],{"type":57,"value":3947},"references\u002Fmastra-studio.md",{"type":57,"value":158},{"type":48,"tag":49,"props":3950,"children":3951},{},[3952,3957],{"type":48,"tag":53,"props":3953,"children":3954},{},[3955],{"type":57,"value":3956},"The fix: call the function directly from the client.",{"type":57,"value":3958}," Don't route the long request through your app server.",{"type":48,"tag":92,"props":3960,"children":3964},{"className":3961,"code":3963,"language":57},[3962],"language-text","Browser ──(Authorization: Bearer \u003CJWT>)──▶  Neon Function (agent)   ✅ no host timeout\nBrowser ──▶ your app backend ──▶ Neon Function                       ❌ host cuts the stream\n",[3965],{"type":48,"tag":62,"props":3966,"children":3967},{"__ignoreMap":97},[3968],{"type":57,"value":3963},{"type":48,"tag":206,"props":3970,"children":3971},{},[3972,3992,4027],{"type":48,"tag":210,"props":3973,"children":3974},{},[3975,3977,3982,3984,3990],{"type":57,"value":3976},"Mint a ",{"type":48,"tag":53,"props":3978,"children":3979},{},[3980],{"type":57,"value":3981},"short-lived JWT",{"type":57,"value":3983}," on your app backend (e.g. better-auth's ",{"type":48,"tag":62,"props":3985,"children":3987},{"className":3986},[],[3988],{"type":57,"value":3989},"jwt",{"type":57,"value":3991}," plugin, NextAuth, or your own signer) — that call is fast and well within host limits.",{"type":48,"tag":210,"props":3993,"children":3994},{},[3995,3997,4001,4003,4009,4011,4017,4019,4025],{"type":57,"value":3996},"Hand the token to the client and have it call the Neon Function ",{"type":48,"tag":53,"props":3998,"children":3999},{},[4000],{"type":57,"value":530},{"type":57,"value":4002}," (cross-origin), e.g. with the Vercel AI SDK: ",{"type":48,"tag":62,"props":4004,"children":4006},{"className":4005},[],[4007],{"type":57,"value":4008},"new DefaultChatTransport({ api: NEON_FUNCTION_URL, fetch })",{"type":57,"value":4010}," where ",{"type":48,"tag":62,"props":4012,"children":4014},{"className":4013},[],[4015],{"type":57,"value":4016},"fetch",{"type":57,"value":4018}," attaches ",{"type":48,"tag":62,"props":4020,"children":4022},{"className":4021},[],[4023],{"type":57,"value":4024},"Authorization: Bearer \u003Ctoken>",{"type":57,"value":4026},". Your app server is never in the path of the long stream.",{"type":48,"tag":210,"props":4028,"children":4029},{},[4030,4032,4037,4039,4045,4047,4053,4054,4060],{"type":57,"value":4031},"Add ",{"type":48,"tag":53,"props":4033,"children":4034},{},[4035],{"type":57,"value":4036},"CORS",{"type":57,"value":4038}," so the browser can reach it (handle ",{"type":48,"tag":62,"props":4040,"children":4042},{"className":4041},[],[4043],{"type":57,"value":4044},"OPTIONS",{"type":57,"value":4046},", set ",{"type":48,"tag":62,"props":4048,"children":4050},{"className":4049},[],[4051],{"type":57,"value":4052},"Access-Control-Allow-Origin",{"type":57,"value":1410},{"type":48,"tag":62,"props":4055,"children":4057},{"className":4056},[],[4058],{"type":57,"value":4059},"-Headers",{"type":57,"value":318},{"type":48,"tag":3676,"props":4062,"children":4063},{},[4064],{"type":48,"tag":49,"props":4065,"children":4066},{},[4067,4072,4074,4079,4081,4086],{"type":48,"tag":103,"props":4068,"children":4069},{},[4070],{"type":57,"value":4071},"!WARNING",{"type":57,"value":4073},"\nA Neon Function has a ",{"type":48,"tag":53,"props":4075,"children":4076},{},[4077],{"type":57,"value":4078},"public HTTPS URL — it is reachable by anyone.",{"type":57,"value":4080}," A direct client→function call means there is no app backend in front of it to gate access, so ",{"type":48,"tag":53,"props":4082,"children":4083},{},[4084],{"type":57,"value":4085},"you must authenticate the function yourself.",{"type":57,"value":4087}," Verify a JWT (e.g. against your app's JWKS), check a shared secret \u002F API key, or validate a session token at the top of the handler and reject anything else. Never deploy an unauthenticated agent.",{"type":48,"tag":92,"props":4089,"children":4091},{"className":615,"code":4090,"language":617,"meta":97,"style":97},"\u002F\u002F src\u002Findex.ts — verify the caller before doing any work\nimport { createRemoteJWKSet, jwtVerify } from \"jose\";\n\nconst jwks = createRemoteJWKSet(new URL(`${process.env.AUTH_BASE_URL}\u002Fapi\u002Fauth\u002Fjwks`));\n\nexport default {\n  async fetch(request: Request) {\n    if (request.method === \"OPTIONS\") return new Response(null, { status: 204, headers: cors(request) });\n\n    const auth = request.headers.get(\"authorization\");\n    if (!auth?.toLowerCase().startsWith(\"bearer \")) {\n      return new Response(\"Unauthorized\", { status: 401, headers: cors(request) });\n    }\n    try {\n      const { payload } = await jwtVerify(auth.slice(7), jwks, {\n        issuer: process.env.AUTH_BASE_URL,\n        audience: process.env.AUTH_BASE_URL,\n      });\n      const userId = payload.sub; \u002F\u002F scope the agent to this user\n      \u002F\u002F ... run the agent, return result.toUIMessageStreamResponse({ headers: cors(request) })\n    } catch {\n      return new Response(\"Unauthorized\", { status: 401, headers: cors(request) });\n    }\n  },\n};\n",[4092],{"type":48,"tag":62,"props":4093,"children":4094},{"__ignoreMap":97},[4095,4103,4153,4160,4247,4254,4269,4308,4437,4444,4508,4577,4671,4679,4691,4771,4807,4843,4859,4897,4905,4922,5013,5021,5029],{"type":48,"tag":103,"props":4096,"children":4097},{"class":105,"line":106},[4098],{"type":48,"tag":103,"props":4099,"children":4100},{"style":627},[4101],{"type":57,"value":4102},"\u002F\u002F src\u002Findex.ts — verify the caller before doing any work\n",{"type":48,"tag":103,"props":4104,"children":4105},{"class":105,"line":633},[4106,4110,4114,4119,4123,4128,4132,4136,4140,4145,4149],{"type":48,"tag":103,"props":4107,"children":4108},{"style":637},[4109],{"type":57,"value":640},{"type":48,"tag":103,"props":4111,"children":4112},{"style":643},[4113],{"type":57,"value":646},{"type":48,"tag":103,"props":4115,"children":4116},{"style":649},[4117],{"type":57,"value":4118}," createRemoteJWKSet",{"type":48,"tag":103,"props":4120,"children":4121},{"style":643},[4122],{"type":57,"value":814},{"type":48,"tag":103,"props":4124,"children":4125},{"style":649},[4126],{"type":57,"value":4127}," jwtVerify",{"type":48,"tag":103,"props":4129,"children":4130},{"style":643},[4131],{"type":57,"value":657},{"type":48,"tag":103,"props":4133,"children":4134},{"style":637},[4135],{"type":57,"value":662},{"type":48,"tag":103,"props":4137,"children":4138},{"style":643},[4139],{"type":57,"value":667},{"type":48,"tag":103,"props":4141,"children":4142},{"style":116},[4143],{"type":57,"value":4144},"jose",{"type":48,"tag":103,"props":4146,"children":4147},{"style":643},[4148],{"type":57,"value":677},{"type":48,"tag":103,"props":4150,"children":4151},{"style":643},[4152],{"type":57,"value":682},{"type":48,"tag":103,"props":4154,"children":4155},{"class":105,"line":685},[4156],{"type":48,"tag":103,"props":4157,"children":4158},{"emptyLinePlaceholder":689},[4159],{"type":57,"value":692},{"type":48,"tag":103,"props":4161,"children":4162},{"class":105,"line":695},[4163,4167,4172,4176,4180,4184,4189,4194,4198,4203,4208,4212,4216,4220,4225,4229,4234,4239,4243],{"type":48,"tag":103,"props":4164,"children":4165},{"style":1188},[4166],{"type":57,"value":1191},{"type":48,"tag":103,"props":4168,"children":4169},{"style":649},[4170],{"type":57,"value":4171}," jwks ",{"type":48,"tag":103,"props":4173,"children":4174},{"style":643},[4175],{"type":57,"value":1201},{"type":48,"tag":103,"props":4177,"children":4178},{"style":709},[4179],{"type":57,"value":4118},{"type":48,"tag":103,"props":4181,"children":4182},{"style":649},[4183],{"type":57,"value":716},{"type":48,"tag":103,"props":4185,"children":4186},{"style":643},[4187],{"type":57,"value":4188},"new",{"type":48,"tag":103,"props":4190,"children":4191},{"style":709},[4192],{"type":57,"value":4193}," URL",{"type":48,"tag":103,"props":4195,"children":4196},{"style":649},[4197],{"type":57,"value":716},{"type":48,"tag":103,"props":4199,"children":4200},{"style":643},[4201],{"type":57,"value":4202},"`${",{"type":48,"tag":103,"props":4204,"children":4205},{"style":649},[4206],{"type":57,"value":4207},"process",{"type":48,"tag":103,"props":4209,"children":4210},{"style":643},[4211],{"type":57,"value":158},{"type":48,"tag":103,"props":4213,"children":4214},{"style":649},[4215],{"type":57,"value":2361},{"type":48,"tag":103,"props":4217,"children":4218},{"style":643},[4219],{"type":57,"value":158},{"type":48,"tag":103,"props":4221,"children":4222},{"style":649},[4223],{"type":57,"value":4224},"AUTH_BASE_URL",{"type":48,"tag":103,"props":4226,"children":4227},{"style":643},[4228],{"type":57,"value":889},{"type":48,"tag":103,"props":4230,"children":4231},{"style":116},[4232],{"type":57,"value":4233},"\u002Fapi\u002Fauth\u002Fjwks",{"type":48,"tag":103,"props":4235,"children":4236},{"style":643},[4237],{"type":57,"value":4238},"`",{"type":48,"tag":103,"props":4240,"children":4241},{"style":649},[4242],{"type":57,"value":1473},{"type":48,"tag":103,"props":4244,"children":4245},{"style":643},[4246],{"type":57,"value":682},{"type":48,"tag":103,"props":4248,"children":4249},{"class":105,"line":724},[4250],{"type":48,"tag":103,"props":4251,"children":4252},{"emptyLinePlaceholder":689},[4253],{"type":57,"value":692},{"type":48,"tag":103,"props":4255,"children":4256},{"class":105,"line":743},[4257,4261,4265],{"type":48,"tag":103,"props":4258,"children":4259},{"style":637},[4260],{"type":57,"value":701},{"type":48,"tag":103,"props":4262,"children":4263},{"style":637},[4264],{"type":57,"value":706},{"type":48,"tag":103,"props":4266,"children":4267},{"style":643},[4268],{"type":57,"value":740},{"type":48,"tag":103,"props":4270,"children":4271},{"class":105,"line":760},[4272,4277,4282,4286,4291,4295,4300,4304],{"type":48,"tag":103,"props":4273,"children":4274},{"style":1188},[4275],{"type":57,"value":4276},"  async",{"type":48,"tag":103,"props":4278,"children":4279},{"style":728},[4280],{"type":57,"value":4281}," fetch",{"type":48,"tag":103,"props":4283,"children":4284},{"style":643},[4285],{"type":57,"value":716},{"type":48,"tag":103,"props":4287,"children":4288},{"style":1426},[4289],{"type":57,"value":4290},"request",{"type":48,"tag":103,"props":4292,"children":4293},{"style":643},[4294],{"type":57,"value":612},{"type":48,"tag":103,"props":4296,"children":4297},{"style":110},[4298],{"type":57,"value":4299}," Request",{"type":48,"tag":103,"props":4301,"children":4302},{"style":643},[4303],{"type":57,"value":894},{"type":48,"tag":103,"props":4305,"children":4306},{"style":643},[4307],{"type":57,"value":740},{"type":48,"tag":103,"props":4309,"children":4310},{"class":105,"line":777},[4311,4316,4320,4324,4328,4333,4338,4342,4346,4350,4355,4360,4364,4369,4373,4378,4382,4386,4390,4395,4399,4404,4408,4413,4417,4421,4425,4429,4433],{"type":48,"tag":103,"props":4312,"children":4313},{"style":637},[4314],{"type":57,"value":4315},"    if",{"type":48,"tag":103,"props":4317,"children":4318},{"style":728},[4319],{"type":57,"value":1423},{"type":48,"tag":103,"props":4321,"children":4322},{"style":649},[4323],{"type":57,"value":4290},{"type":48,"tag":103,"props":4325,"children":4326},{"style":643},[4327],{"type":57,"value":158},{"type":48,"tag":103,"props":4329,"children":4330},{"style":649},[4331],{"type":57,"value":4332},"method",{"type":48,"tag":103,"props":4334,"children":4335},{"style":643},[4336],{"type":57,"value":4337}," ===",{"type":48,"tag":103,"props":4339,"children":4340},{"style":643},[4341],{"type":57,"value":667},{"type":48,"tag":103,"props":4343,"children":4344},{"style":116},[4345],{"type":57,"value":4044},{"type":48,"tag":103,"props":4347,"children":4348},{"style":643},[4349],{"type":57,"value":677},{"type":48,"tag":103,"props":4351,"children":4352},{"style":728},[4353],{"type":57,"value":4354},") ",{"type":48,"tag":103,"props":4356,"children":4357},{"style":637},[4358],{"type":57,"value":4359},"return",{"type":48,"tag":103,"props":4361,"children":4362},{"style":643},[4363],{"type":57,"value":1235},{"type":48,"tag":103,"props":4365,"children":4366},{"style":709},[4367],{"type":57,"value":4368}," Response",{"type":48,"tag":103,"props":4370,"children":4371},{"style":728},[4372],{"type":57,"value":716},{"type":48,"tag":103,"props":4374,"children":4375},{"style":643},[4376],{"type":57,"value":4377},"null,",{"type":48,"tag":103,"props":4379,"children":4380},{"style":643},[4381],{"type":57,"value":646},{"type":48,"tag":103,"props":4383,"children":4384},{"style":728},[4385],{"type":57,"value":2394},{"type":48,"tag":103,"props":4387,"children":4388},{"style":643},[4389],{"type":57,"value":612},{"type":48,"tag":103,"props":4391,"children":4392},{"style":1296},[4393],{"type":57,"value":4394}," 204",{"type":48,"tag":103,"props":4396,"children":4397},{"style":643},[4398],{"type":57,"value":814},{"type":48,"tag":103,"props":4400,"children":4401},{"style":728},[4402],{"type":57,"value":4403}," headers",{"type":48,"tag":103,"props":4405,"children":4406},{"style":643},[4407],{"type":57,"value":612},{"type":48,"tag":103,"props":4409,"children":4410},{"style":709},[4411],{"type":57,"value":4412}," cors",{"type":48,"tag":103,"props":4414,"children":4415},{"style":728},[4416],{"type":57,"value":716},{"type":48,"tag":103,"props":4418,"children":4419},{"style":649},[4420],{"type":57,"value":4290},{"type":48,"tag":103,"props":4422,"children":4423},{"style":728},[4424],{"type":57,"value":4354},{"type":48,"tag":103,"props":4426,"children":4427},{"style":643},[4428],{"type":57,"value":889},{"type":48,"tag":103,"props":4430,"children":4431},{"style":728},[4432],{"type":57,"value":894},{"type":48,"tag":103,"props":4434,"children":4435},{"style":643},[4436],{"type":57,"value":682},{"type":48,"tag":103,"props":4438,"children":4439},{"class":105,"line":786},[4440],{"type":48,"tag":103,"props":4441,"children":4442},{"emptyLinePlaceholder":689},[4443],{"type":57,"value":692},{"type":48,"tag":103,"props":4445,"children":4446},{"class":105,"line":822},[4447,4452,4457,4461,4466,4470,4475,4479,4483,4487,4491,4496,4500,4504],{"type":48,"tag":103,"props":4448,"children":4449},{"style":1188},[4450],{"type":57,"value":4451},"    const",{"type":48,"tag":103,"props":4453,"children":4454},{"style":649},[4455],{"type":57,"value":4456}," auth",{"type":48,"tag":103,"props":4458,"children":4459},{"style":643},[4460],{"type":57,"value":1567},{"type":48,"tag":103,"props":4462,"children":4463},{"style":649},[4464],{"type":57,"value":4465}," request",{"type":48,"tag":103,"props":4467,"children":4468},{"style":643},[4469],{"type":57,"value":158},{"type":48,"tag":103,"props":4471,"children":4472},{"style":649},[4473],{"type":57,"value":4474},"headers",{"type":48,"tag":103,"props":4476,"children":4477},{"style":643},[4478],{"type":57,"value":158},{"type":48,"tag":103,"props":4480,"children":4481},{"style":709},[4482],{"type":57,"value":1397},{"type":48,"tag":103,"props":4484,"children":4485},{"style":728},[4486],{"type":57,"value":716},{"type":48,"tag":103,"props":4488,"children":4489},{"style":643},[4490],{"type":57,"value":677},{"type":48,"tag":103,"props":4492,"children":4493},{"style":116},[4494],{"type":57,"value":4495},"authorization",{"type":48,"tag":103,"props":4497,"children":4498},{"style":643},[4499],{"type":57,"value":677},{"type":48,"tag":103,"props":4501,"children":4502},{"style":728},[4503],{"type":57,"value":894},{"type":48,"tag":103,"props":4505,"children":4506},{"style":643},[4507],{"type":57,"value":682},{"type":48,"tag":103,"props":4509,"children":4510},{"class":105,"line":857},[4511,4515,4519,4523,4528,4533,4538,4542,4546,4551,4555,4559,4564,4568,4573],{"type":48,"tag":103,"props":4512,"children":4513},{"style":637},[4514],{"type":57,"value":4315},{"type":48,"tag":103,"props":4516,"children":4517},{"style":728},[4518],{"type":57,"value":1423},{"type":48,"tag":103,"props":4520,"children":4521},{"style":643},[4522],{"type":57,"value":3215},{"type":48,"tag":103,"props":4524,"children":4525},{"style":649},[4526],{"type":57,"value":4527},"auth",{"type":48,"tag":103,"props":4529,"children":4530},{"style":643},[4531],{"type":57,"value":4532},"?.",{"type":48,"tag":103,"props":4534,"children":4535},{"style":709},[4536],{"type":57,"value":4537},"toLowerCase",{"type":48,"tag":103,"props":4539,"children":4540},{"style":728},[4541],{"type":57,"value":1376},{"type":48,"tag":103,"props":4543,"children":4544},{"style":643},[4545],{"type":57,"value":158},{"type":48,"tag":103,"props":4547,"children":4548},{"style":709},[4549],{"type":57,"value":4550},"startsWith",{"type":48,"tag":103,"props":4552,"children":4553},{"style":728},[4554],{"type":57,"value":716},{"type":48,"tag":103,"props":4556,"children":4557},{"style":643},[4558],{"type":57,"value":677},{"type":48,"tag":103,"props":4560,"children":4561},{"style":116},[4562],{"type":57,"value":4563},"bearer ",{"type":48,"tag":103,"props":4565,"children":4566},{"style":643},[4567],{"type":57,"value":677},{"type":48,"tag":103,"props":4569,"children":4570},{"style":728},[4571],{"type":57,"value":4572},")) ",{"type":48,"tag":103,"props":4574,"children":4575},{"style":643},[4576],{"type":57,"value":721},{"type":48,"tag":103,"props":4578,"children":4579},{"class":105,"line":34},[4580,4585,4589,4593,4597,4601,4606,4610,4614,4618,4622,4626,4631,4635,4639,4643,4647,4651,4655,4659,4663,4667],{"type":48,"tag":103,"props":4581,"children":4582},{"style":637},[4583],{"type":57,"value":4584},"      return",{"type":48,"tag":103,"props":4586,"children":4587},{"style":643},[4588],{"type":57,"value":1235},{"type":48,"tag":103,"props":4590,"children":4591},{"style":709},[4592],{"type":57,"value":4368},{"type":48,"tag":103,"props":4594,"children":4595},{"style":728},[4596],{"type":57,"value":716},{"type":48,"tag":103,"props":4598,"children":4599},{"style":643},[4600],{"type":57,"value":677},{"type":48,"tag":103,"props":4602,"children":4603},{"style":116},[4604],{"type":57,"value":4605},"Unauthorized",{"type":48,"tag":103,"props":4607,"children":4608},{"style":643},[4609],{"type":57,"value":677},{"type":48,"tag":103,"props":4611,"children":4612},{"style":643},[4613],{"type":57,"value":814},{"type":48,"tag":103,"props":4615,"children":4616},{"style":643},[4617],{"type":57,"value":646},{"type":48,"tag":103,"props":4619,"children":4620},{"style":728},[4621],{"type":57,"value":2394},{"type":48,"tag":103,"props":4623,"children":4624},{"style":643},[4625],{"type":57,"value":612},{"type":48,"tag":103,"props":4627,"children":4628},{"style":1296},[4629],{"type":57,"value":4630}," 401",{"type":48,"tag":103,"props":4632,"children":4633},{"style":643},[4634],{"type":57,"value":814},{"type":48,"tag":103,"props":4636,"children":4637},{"style":728},[4638],{"type":57,"value":4403},{"type":48,"tag":103,"props":4640,"children":4641},{"style":643},[4642],{"type":57,"value":612},{"type":48,"tag":103,"props":4644,"children":4645},{"style":709},[4646],{"type":57,"value":4412},{"type":48,"tag":103,"props":4648,"children":4649},{"style":728},[4650],{"type":57,"value":716},{"type":48,"tag":103,"props":4652,"children":4653},{"style":649},[4654],{"type":57,"value":4290},{"type":48,"tag":103,"props":4656,"children":4657},{"style":728},[4658],{"type":57,"value":4354},{"type":48,"tag":103,"props":4660,"children":4661},{"style":643},[4662],{"type":57,"value":889},{"type":48,"tag":103,"props":4664,"children":4665},{"style":728},[4666],{"type":57,"value":894},{"type":48,"tag":103,"props":4668,"children":4669},{"style":643},[4670],{"type":57,"value":682},{"type":48,"tag":103,"props":4672,"children":4673},{"class":105,"line":874},[4674],{"type":48,"tag":103,"props":4675,"children":4676},{"style":643},[4677],{"type":57,"value":4678},"    }\n",{"type":48,"tag":103,"props":4680,"children":4681},{"class":105,"line":883},[4682,4687],{"type":48,"tag":103,"props":4683,"children":4684},{"style":637},[4685],{"type":57,"value":4686},"    try",{"type":48,"tag":103,"props":4688,"children":4689},{"style":643},[4690],{"type":57,"value":740},{"type":48,"tag":103,"props":4692,"children":4693},{"class":105,"line":1480},[4694,4699,4703,4708,4712,4716,4720,4724,4728,4732,4736,4741,4745,4750,4754,4758,4763,4767],{"type":48,"tag":103,"props":4695,"children":4696},{"style":1188},[4697],{"type":57,"value":4698},"      const",{"type":48,"tag":103,"props":4700,"children":4701},{"style":643},[4702],{"type":57,"value":646},{"type":48,"tag":103,"props":4704,"children":4705},{"style":649},[4706],{"type":57,"value":4707}," payload",{"type":48,"tag":103,"props":4709,"children":4710},{"style":643},[4711],{"type":57,"value":657},{"type":48,"tag":103,"props":4713,"children":4714},{"style":643},[4715],{"type":57,"value":1567},{"type":48,"tag":103,"props":4717,"children":4718},{"style":637},[4719],{"type":57,"value":1572},{"type":48,"tag":103,"props":4721,"children":4722},{"style":709},[4723],{"type":57,"value":4127},{"type":48,"tag":103,"props":4725,"children":4726},{"style":728},[4727],{"type":57,"value":716},{"type":48,"tag":103,"props":4729,"children":4730},{"style":649},[4731],{"type":57,"value":4527},{"type":48,"tag":103,"props":4733,"children":4734},{"style":643},[4735],{"type":57,"value":158},{"type":48,"tag":103,"props":4737,"children":4738},{"style":709},[4739],{"type":57,"value":4740},"slice",{"type":48,"tag":103,"props":4742,"children":4743},{"style":728},[4744],{"type":57,"value":716},{"type":48,"tag":103,"props":4746,"children":4747},{"style":1296},[4748],{"type":57,"value":4749},"7",{"type":48,"tag":103,"props":4751,"children":4752},{"style":728},[4753],{"type":57,"value":894},{"type":48,"tag":103,"props":4755,"children":4756},{"style":643},[4757],{"type":57,"value":814},{"type":48,"tag":103,"props":4759,"children":4760},{"style":649},[4761],{"type":57,"value":4762}," jwks",{"type":48,"tag":103,"props":4764,"children":4765},{"style":643},[4766],{"type":57,"value":814},{"type":48,"tag":103,"props":4768,"children":4769},{"style":643},[4770],{"type":57,"value":740},{"type":48,"tag":103,"props":4772,"children":4773},{"class":105,"line":1543},[4774,4779,4783,4787,4791,4795,4799,4803],{"type":48,"tag":103,"props":4775,"children":4776},{"style":728},[4777],{"type":57,"value":4778},"        issuer",{"type":48,"tag":103,"props":4780,"children":4781},{"style":643},[4782],{"type":57,"value":612},{"type":48,"tag":103,"props":4784,"children":4785},{"style":649},[4786],{"type":57,"value":3193},{"type":48,"tag":103,"props":4788,"children":4789},{"style":643},[4790],{"type":57,"value":158},{"type":48,"tag":103,"props":4792,"children":4793},{"style":649},[4794],{"type":57,"value":2361},{"type":48,"tag":103,"props":4796,"children":4797},{"style":643},[4798],{"type":57,"value":158},{"type":48,"tag":103,"props":4800,"children":4801},{"style":649},[4802],{"type":57,"value":4224},{"type":48,"tag":103,"props":4804,"children":4805},{"style":643},[4806],{"type":57,"value":2770},{"type":48,"tag":103,"props":4808,"children":4809},{"class":105,"line":1628},[4810,4815,4819,4823,4827,4831,4835,4839],{"type":48,"tag":103,"props":4811,"children":4812},{"style":728},[4813],{"type":57,"value":4814},"        audience",{"type":48,"tag":103,"props":4816,"children":4817},{"style":643},[4818],{"type":57,"value":612},{"type":48,"tag":103,"props":4820,"children":4821},{"style":649},[4822],{"type":57,"value":3193},{"type":48,"tag":103,"props":4824,"children":4825},{"style":643},[4826],{"type":57,"value":158},{"type":48,"tag":103,"props":4828,"children":4829},{"style":649},[4830],{"type":57,"value":2361},{"type":48,"tag":103,"props":4832,"children":4833},{"style":643},[4834],{"type":57,"value":158},{"type":48,"tag":103,"props":4836,"children":4837},{"style":649},[4838],{"type":57,"value":4224},{"type":48,"tag":103,"props":4840,"children":4841},{"style":643},[4842],{"type":57,"value":2770},{"type":48,"tag":103,"props":4844,"children":4845},{"class":105,"line":1732},[4846,4851,4855],{"type":48,"tag":103,"props":4847,"children":4848},{"style":643},[4849],{"type":57,"value":4850},"      }",{"type":48,"tag":103,"props":4852,"children":4853},{"style":728},[4854],{"type":57,"value":894},{"type":48,"tag":103,"props":4856,"children":4857},{"style":643},[4858],{"type":57,"value":682},{"type":48,"tag":103,"props":4860,"children":4861},{"class":105,"line":1778},[4862,4866,4871,4875,4879,4883,4888,4892],{"type":48,"tag":103,"props":4863,"children":4864},{"style":1188},[4865],{"type":57,"value":4698},{"type":48,"tag":103,"props":4867,"children":4868},{"style":649},[4869],{"type":57,"value":4870}," userId",{"type":48,"tag":103,"props":4872,"children":4873},{"style":643},[4874],{"type":57,"value":1567},{"type":48,"tag":103,"props":4876,"children":4877},{"style":649},[4878],{"type":57,"value":4707},{"type":48,"tag":103,"props":4880,"children":4881},{"style":643},[4882],{"type":57,"value":158},{"type":48,"tag":103,"props":4884,"children":4885},{"style":649},[4886],{"type":57,"value":4887},"sub",{"type":48,"tag":103,"props":4889,"children":4890},{"style":643},[4891],{"type":57,"value":2054},{"type":48,"tag":103,"props":4893,"children":4894},{"style":627},[4895],{"type":57,"value":4896}," \u002F\u002F scope the agent to this user\n",{"type":48,"tag":103,"props":4898,"children":4899},{"class":105,"line":1794},[4900],{"type":48,"tag":103,"props":4901,"children":4902},{"style":627},[4903],{"type":57,"value":4904},"      \u002F\u002F ... run the agent, return result.toUIMessageStreamResponse({ headers: cors(request) })\n",{"type":48,"tag":103,"props":4906,"children":4907},{"class":105,"line":1905},[4908,4913,4918],{"type":48,"tag":103,"props":4909,"children":4910},{"style":643},[4911],{"type":57,"value":4912},"    }",{"type":48,"tag":103,"props":4914,"children":4915},{"style":637},[4916],{"type":57,"value":4917}," catch",{"type":48,"tag":103,"props":4919,"children":4920},{"style":643},[4921],{"type":57,"value":740},{"type":48,"tag":103,"props":4923,"children":4924},{"class":105,"line":1913},[4925,4929,4933,4937,4941,4945,4949,4953,4957,4961,4965,4969,4973,4977,4981,4985,4989,4993,4997,5001,5005,5009],{"type":48,"tag":103,"props":4926,"children":4927},{"style":637},[4928],{"type":57,"value":4584},{"type":48,"tag":103,"props":4930,"children":4931},{"style":643},[4932],{"type":57,"value":1235},{"type":48,"tag":103,"props":4934,"children":4935},{"style":709},[4936],{"type":57,"value":4368},{"type":48,"tag":103,"props":4938,"children":4939},{"style":728},[4940],{"type":57,"value":716},{"type":48,"tag":103,"props":4942,"children":4943},{"style":643},[4944],{"type":57,"value":677},{"type":48,"tag":103,"props":4946,"children":4947},{"style":116},[4948],{"type":57,"value":4605},{"type":48,"tag":103,"props":4950,"children":4951},{"style":643},[4952],{"type":57,"value":677},{"type":48,"tag":103,"props":4954,"children":4955},{"style":643},[4956],{"type":57,"value":814},{"type":48,"tag":103,"props":4958,"children":4959},{"style":643},[4960],{"type":57,"value":646},{"type":48,"tag":103,"props":4962,"children":4963},{"style":728},[4964],{"type":57,"value":2394},{"type":48,"tag":103,"props":4966,"children":4967},{"style":643},[4968],{"type":57,"value":612},{"type":48,"tag":103,"props":4970,"children":4971},{"style":1296},[4972],{"type":57,"value":4630},{"type":48,"tag":103,"props":4974,"children":4975},{"style":643},[4976],{"type":57,"value":814},{"type":48,"tag":103,"props":4978,"children":4979},{"style":728},[4980],{"type":57,"value":4403},{"type":48,"tag":103,"props":4982,"children":4983},{"style":643},[4984],{"type":57,"value":612},{"type":48,"tag":103,"props":4986,"children":4987},{"style":709},[4988],{"type":57,"value":4412},{"type":48,"tag":103,"props":4990,"children":4991},{"style":728},[4992],{"type":57,"value":716},{"type":48,"tag":103,"props":4994,"children":4995},{"style":649},[4996],{"type":57,"value":4290},{"type":48,"tag":103,"props":4998,"children":4999},{"style":728},[5000],{"type":57,"value":4354},{"type":48,"tag":103,"props":5002,"children":5003},{"style":643},[5004],{"type":57,"value":889},{"type":48,"tag":103,"props":5006,"children":5007},{"style":728},[5008],{"type":57,"value":894},{"type":48,"tag":103,"props":5010,"children":5011},{"style":643},[5012],{"type":57,"value":682},{"type":48,"tag":103,"props":5014,"children":5016},{"class":105,"line":5015},23,[5017],{"type":48,"tag":103,"props":5018,"children":5019},{"style":643},[5020],{"type":57,"value":4678},{"type":48,"tag":103,"props":5022,"children":5024},{"class":105,"line":5023},24,[5025],{"type":48,"tag":103,"props":5026,"children":5027},{"style":643},[5028],{"type":57,"value":880},{"type":48,"tag":103,"props":5030,"children":5032},{"class":105,"line":5031},25,[5033],{"type":48,"tag":103,"props":5034,"children":5035},{"style":643},[5036],{"type":57,"value":5037},"};\n",{"type":48,"tag":49,"props":5039,"children":5040},{},[5041,5043,5048,5050,5055],{"type":57,"value":5042},"Pass the JWKS\u002Fissuer URL to the function via its ",{"type":48,"tag":62,"props":5044,"children":5046},{"className":5045},[],[5047],{"type":57,"value":2361},{"type":57,"value":5049}," (see ",{"type":48,"tag":82,"props":5051,"children":5053},{"href":5052},"#environment-variables",[5054],{"type":57,"value":2791},{"type":57,"value":5056},"). Persist anything you need to keep (generated images, history) in Postgres — module state doesn't survive eviction.",{"type":48,"tag":194,"props":5058,"children":5060},{"id":5059},"websocket-servers",[5061],{"type":57,"value":343},{"type":48,"tag":49,"props":5063,"children":5064},{},[5065,5067,5078,5080,5085],{"type":57,"value":5066},"A WebSocket server is the canonical Functions workload: a long-running handler holds connections open in-process, with no external state store needed to keep a stream coherent. Because a function is a real Node.js process (not a lambda), the WebSocket handshake works the way it does in any Node server — the ",{"type":48,"tag":82,"props":5068,"children":5071},{"href":5069,"rel":5070},"https:\u002F\u002Fgithub.com\u002Fwebsockets\u002Fws",[86],[5072],{"type":48,"tag":62,"props":5073,"children":5075},{"className":5074},[],[5076],{"type":57,"value":5077},"ws",{"type":57,"value":5079}," library upgrades the socket, and the connection stays alive as long as bytes flow (15-minute heartbeat, see ",{"type":48,"tag":82,"props":5081,"children":5082},{"href":305},[5083],{"type":57,"value":5084},"Timeouts",{"type":57,"value":318},{"type":48,"tag":49,"props":5087,"children":5088},{},[5089,5094,5096,5102,5104,5110,5112,5117,5119,5124],{"type":48,"tag":53,"props":5090,"children":5091},{},[5092],{"type":57,"value":5093},"The return signature is the whole trick.",{"type":57,"value":5095}," A function's default export is normally ",{"type":48,"tag":62,"props":5097,"children":5099},{"className":5098},[],[5100],{"type":57,"value":5101},"{ fetch }",{"type":57,"value":5103},". To also accept WebSockets, export an ",{"type":48,"tag":62,"props":5105,"children":5107},{"className":5106},[],[5108],{"type":57,"value":5109},"upgrade",{"type":57,"value":5111}," method alongside it — the runtime routes plain HTTP to ",{"type":48,"tag":62,"props":5113,"children":5115},{"className":5114},[],[5116],{"type":57,"value":4016},{"type":57,"value":5118}," and the WebSocket handshake to ",{"type":48,"tag":62,"props":5120,"children":5122},{"className":5121},[],[5123],{"type":57,"value":5109},{"type":57,"value":612},{"type":48,"tag":92,"props":5126,"children":5128},{"className":615,"code":5127,"language":617,"meta":97,"style":97},"export default {\n  fetch(request: Request): Response | Promise\u003CResponse> { \u002F* HTTP *\u002F },\n  async upgrade(req: IncomingMessage, socket: Duplex, head: Buffer) { \u002F* WS handshake *\u002F },\n};\n",[5129],{"type":48,"tag":62,"props":5130,"children":5131},{"__ignoreMap":97},[5132,5147,5216,5298],{"type":48,"tag":103,"props":5133,"children":5134},{"class":105,"line":106},[5135,5139,5143],{"type":48,"tag":103,"props":5136,"children":5137},{"style":637},[5138],{"type":57,"value":701},{"type":48,"tag":103,"props":5140,"children":5141},{"style":637},[5142],{"type":57,"value":706},{"type":48,"tag":103,"props":5144,"children":5145},{"style":643},[5146],{"type":57,"value":740},{"type":48,"tag":103,"props":5148,"children":5149},{"class":105,"line":633},[5150,5155,5159,5163,5167,5171,5175,5179,5184,5189,5194,5198,5203,5207,5212],{"type":48,"tag":103,"props":5151,"children":5152},{"style":728},[5153],{"type":57,"value":5154},"  fetch",{"type":48,"tag":103,"props":5156,"children":5157},{"style":643},[5158],{"type":57,"value":716},{"type":48,"tag":103,"props":5160,"children":5161},{"style":1426},[5162],{"type":57,"value":4290},{"type":48,"tag":103,"props":5164,"children":5165},{"style":643},[5166],{"type":57,"value":612},{"type":48,"tag":103,"props":5168,"children":5169},{"style":110},[5170],{"type":57,"value":4299},{"type":48,"tag":103,"props":5172,"children":5173},{"style":643},[5174],{"type":57,"value":1984},{"type":48,"tag":103,"props":5176,"children":5177},{"style":110},[5178],{"type":57,"value":4368},{"type":48,"tag":103,"props":5180,"children":5181},{"style":643},[5182],{"type":57,"value":5183}," |",{"type":48,"tag":103,"props":5185,"children":5186},{"style":110},[5187],{"type":57,"value":5188}," Promise",{"type":48,"tag":103,"props":5190,"children":5191},{"style":643},[5192],{"type":57,"value":5193},"\u003C",{"type":48,"tag":103,"props":5195,"children":5196},{"style":110},[5197],{"type":57,"value":377},{"type":48,"tag":103,"props":5199,"children":5200},{"style":643},[5201],{"type":57,"value":5202},">",{"type":48,"tag":103,"props":5204,"children":5205},{"style":643},[5206],{"type":57,"value":646},{"type":48,"tag":103,"props":5208,"children":5209},{"style":627},[5210],{"type":57,"value":5211}," \u002F* HTTP *\u002F",{"type":48,"tag":103,"props":5213,"children":5214},{"style":643},[5215],{"type":57,"value":2635},{"type":48,"tag":103,"props":5217,"children":5218},{"class":105,"line":685},[5219,5223,5228,5232,5236,5240,5245,5249,5254,5258,5263,5267,5272,5276,5281,5285,5289,5294],{"type":48,"tag":103,"props":5220,"children":5221},{"style":1188},[5222],{"type":57,"value":4276},{"type":48,"tag":103,"props":5224,"children":5225},{"style":728},[5226],{"type":57,"value":5227}," upgrade",{"type":48,"tag":103,"props":5229,"children":5230},{"style":643},[5231],{"type":57,"value":716},{"type":48,"tag":103,"props":5233,"children":5234},{"style":1426},[5235],{"type":57,"value":1585},{"type":48,"tag":103,"props":5237,"children":5238},{"style":643},[5239],{"type":57,"value":612},{"type":48,"tag":103,"props":5241,"children":5242},{"style":110},[5243],{"type":57,"value":5244}," IncomingMessage",{"type":48,"tag":103,"props":5246,"children":5247},{"style":643},[5248],{"type":57,"value":814},{"type":48,"tag":103,"props":5250,"children":5251},{"style":1426},[5252],{"type":57,"value":5253}," socket",{"type":48,"tag":103,"props":5255,"children":5256},{"style":643},[5257],{"type":57,"value":612},{"type":48,"tag":103,"props":5259,"children":5260},{"style":110},[5261],{"type":57,"value":5262}," Duplex",{"type":48,"tag":103,"props":5264,"children":5265},{"style":643},[5266],{"type":57,"value":814},{"type":48,"tag":103,"props":5268,"children":5269},{"style":1426},[5270],{"type":57,"value":5271}," head",{"type":48,"tag":103,"props":5273,"children":5274},{"style":643},[5275],{"type":57,"value":612},{"type":48,"tag":103,"props":5277,"children":5278},{"style":110},[5279],{"type":57,"value":5280}," Buffer",{"type":48,"tag":103,"props":5282,"children":5283},{"style":643},[5284],{"type":57,"value":894},{"type":48,"tag":103,"props":5286,"children":5287},{"style":643},[5288],{"type":57,"value":646},{"type":48,"tag":103,"props":5290,"children":5291},{"style":627},[5292],{"type":57,"value":5293}," \u002F* WS handshake *\u002F",{"type":48,"tag":103,"props":5295,"children":5296},{"style":643},[5297],{"type":57,"value":2635},{"type":48,"tag":103,"props":5299,"children":5300},{"class":105,"line":695},[5301],{"type":48,"tag":103,"props":5302,"children":5303},{"style":643},[5304],{"type":57,"value":5037},{"type":48,"tag":49,"props":5306,"children":5307},{},[5308,5313,5315,5320,5322,5328,5330,5335,5336,5342],{"type":48,"tag":53,"props":5309,"children":5310},{},[5311],{"type":57,"value":5312},"Simple example",{"type":57,"value":5314}," — raw ",{"type":48,"tag":62,"props":5316,"children":5318},{"className":5317},[],[5319],{"type":57,"value":5077},{"type":57,"value":5321},", no framework, with auth. Browsers can't set headers on a WebSocket, so authenticate with a ",{"type":48,"tag":62,"props":5323,"children":5325},{"className":5324},[],[5326],{"type":57,"value":5327},"?token=",{"type":57,"value":5329}," query param (verify it the same way as the ",{"type":48,"tag":82,"props":5331,"children":5332},{"href":503},[5333],{"type":57,"value":5334},"agent backend",{"type":57,"value":2198},{"type":48,"tag":62,"props":5337,"children":5339},{"className":5338},[],[5340],{"type":57,"value":5341},"jwtVerify",{"type":57,"value":5343}," against your JWKS) before accepting the connection:",{"type":48,"tag":92,"props":5345,"children":5347},{"className":615,"code":5346,"language":617,"meta":97,"style":97},"\u002F\u002F src\u002Findex.ts\nimport type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport { WebSocketServer, type WebSocket } from \"ws\";\n\nconst clients = new Set\u003CWebSocket>();\nconst wss = new WebSocketServer({ noServer: true });\n\nexport default {\n  \u002F\u002F Plain HTTP (health checks, REST) is handled by fetch.\n  fetch: () => new Response(\"WebSocket endpoint — connect with ?token=\u003Cjwt>\"),\n\n  \u002F\u002F The runtime hands the WebSocket handshake to upgrade().\n  async upgrade(req: IncomingMessage, socket: Duplex, head: Buffer) {\n    const url = new URL(req.url ?? \"\u002F\", \"http:\u002F\u002Flocalhost\");\n    const identity = await verifyToken(url.searchParams.get(\"token\")); \u002F\u002F reject if invalid\n    if (!identity) {\n      socket.write(\"HTTP\u002F1.1 401 Unauthorized\\r\\n\\r\\n\");\n      socket.destroy();\n      return;\n    }\n    wss.handleUpgrade(req, socket, head, (ws) => {\n      clients.add(ws);\n      ws.on(\"close\", () => clients.delete(ws));\n      ws.on(\"message\", (data) => persist(data.toString())); \u002F\u002F persist; fan out to every isolate — see below\n    });\n  },\n};\n",[5348],{"type":48,"tag":62,"props":5349,"children":5350},{"__ignoreMap":97},[5351,5358,5403,5447,5500,5507,5553,5612,5619,5634,5642,5695,5702,5710,5777,5860,5940,5968,6015,6039,6050,6057,6122,6155,6231,6320,6336,6344],{"type":48,"tag":103,"props":5352,"children":5353},{"class":105,"line":106},[5354],{"type":48,"tag":103,"props":5355,"children":5356},{"style":627},[5357],{"type":57,"value":937},{"type":48,"tag":103,"props":5359,"children":5360},{"class":105,"line":633},[5361,5365,5370,5374,5378,5382,5386,5390,5395,5399],{"type":48,"tag":103,"props":5362,"children":5363},{"style":637},[5364],{"type":57,"value":640},{"type":48,"tag":103,"props":5366,"children":5367},{"style":637},[5368],{"type":57,"value":5369}," type",{"type":48,"tag":103,"props":5371,"children":5372},{"style":643},[5373],{"type":57,"value":646},{"type":48,"tag":103,"props":5375,"children":5376},{"style":649},[5377],{"type":57,"value":5244},{"type":48,"tag":103,"props":5379,"children":5380},{"style":643},[5381],{"type":57,"value":657},{"type":48,"tag":103,"props":5383,"children":5384},{"style":637},[5385],{"type":57,"value":662},{"type":48,"tag":103,"props":5387,"children":5388},{"style":643},[5389],{"type":57,"value":667},{"type":48,"tag":103,"props":5391,"children":5392},{"style":116},[5393],{"type":57,"value":5394},"node:http",{"type":48,"tag":103,"props":5396,"children":5397},{"style":643},[5398],{"type":57,"value":677},{"type":48,"tag":103,"props":5400,"children":5401},{"style":643},[5402],{"type":57,"value":682},{"type":48,"tag":103,"props":5404,"children":5405},{"class":105,"line":685},[5406,5410,5414,5418,5422,5426,5430,5434,5439,5443],{"type":48,"tag":103,"props":5407,"children":5408},{"style":637},[5409],{"type":57,"value":640},{"type":48,"tag":103,"props":5411,"children":5412},{"style":637},[5413],{"type":57,"value":5369},{"type":48,"tag":103,"props":5415,"children":5416},{"style":643},[5417],{"type":57,"value":646},{"type":48,"tag":103,"props":5419,"children":5420},{"style":649},[5421],{"type":57,"value":5262},{"type":48,"tag":103,"props":5423,"children":5424},{"style":643},[5425],{"type":57,"value":657},{"type":48,"tag":103,"props":5427,"children":5428},{"style":637},[5429],{"type":57,"value":662},{"type":48,"tag":103,"props":5431,"children":5432},{"style":643},[5433],{"type":57,"value":667},{"type":48,"tag":103,"props":5435,"children":5436},{"style":116},[5437],{"type":57,"value":5438},"node:stream",{"type":48,"tag":103,"props":5440,"children":5441},{"style":643},[5442],{"type":57,"value":677},{"type":48,"tag":103,"props":5444,"children":5445},{"style":643},[5446],{"type":57,"value":682},{"type":48,"tag":103,"props":5448,"children":5449},{"class":105,"line":695},[5450,5454,5458,5463,5467,5471,5476,5480,5484,5488,5492,5496],{"type":48,"tag":103,"props":5451,"children":5452},{"style":637},[5453],{"type":57,"value":640},{"type":48,"tag":103,"props":5455,"children":5456},{"style":643},[5457],{"type":57,"value":646},{"type":48,"tag":103,"props":5459,"children":5460},{"style":649},[5461],{"type":57,"value":5462}," WebSocketServer",{"type":48,"tag":103,"props":5464,"children":5465},{"style":643},[5466],{"type":57,"value":814},{"type":48,"tag":103,"props":5468,"children":5469},{"style":637},[5470],{"type":57,"value":5369},{"type":48,"tag":103,"props":5472,"children":5473},{"style":649},[5474],{"type":57,"value":5475}," WebSocket",{"type":48,"tag":103,"props":5477,"children":5478},{"style":643},[5479],{"type":57,"value":657},{"type":48,"tag":103,"props":5481,"children":5482},{"style":637},[5483],{"type":57,"value":662},{"type":48,"tag":103,"props":5485,"children":5486},{"style":643},[5487],{"type":57,"value":667},{"type":48,"tag":103,"props":5489,"children":5490},{"style":116},[5491],{"type":57,"value":5077},{"type":48,"tag":103,"props":5493,"children":5494},{"style":643},[5495],{"type":57,"value":677},{"type":48,"tag":103,"props":5497,"children":5498},{"style":643},[5499],{"type":57,"value":682},{"type":48,"tag":103,"props":5501,"children":5502},{"class":105,"line":724},[5503],{"type":48,"tag":103,"props":5504,"children":5505},{"emptyLinePlaceholder":689},[5506],{"type":57,"value":692},{"type":48,"tag":103,"props":5508,"children":5509},{"class":105,"line":743},[5510,5514,5519,5523,5527,5532,5536,5541,5545,5549],{"type":48,"tag":103,"props":5511,"children":5512},{"style":1188},[5513],{"type":57,"value":1191},{"type":48,"tag":103,"props":5515,"children":5516},{"style":649},[5517],{"type":57,"value":5518}," clients ",{"type":48,"tag":103,"props":5520,"children":5521},{"style":643},[5522],{"type":57,"value":1201},{"type":48,"tag":103,"props":5524,"children":5525},{"style":643},[5526],{"type":57,"value":1235},{"type":48,"tag":103,"props":5528,"children":5529},{"style":709},[5530],{"type":57,"value":5531}," Set",{"type":48,"tag":103,"props":5533,"children":5534},{"style":643},[5535],{"type":57,"value":5193},{"type":48,"tag":103,"props":5537,"children":5538},{"style":110},[5539],{"type":57,"value":5540},"WebSocket",{"type":48,"tag":103,"props":5542,"children":5543},{"style":643},[5544],{"type":57,"value":5202},{"type":48,"tag":103,"props":5546,"children":5547},{"style":649},[5548],{"type":57,"value":1376},{"type":48,"tag":103,"props":5550,"children":5551},{"style":643},[5552],{"type":57,"value":682},{"type":48,"tag":103,"props":5554,"children":5555},{"class":105,"line":760},[5556,5560,5565,5569,5573,5577,5581,5585,5590,5594,5600,5604,5608],{"type":48,"tag":103,"props":5557,"children":5558},{"style":1188},[5559],{"type":57,"value":1191},{"type":48,"tag":103,"props":5561,"children":5562},{"style":649},[5563],{"type":57,"value":5564}," wss ",{"type":48,"tag":103,"props":5566,"children":5567},{"style":643},[5568],{"type":57,"value":1201},{"type":48,"tag":103,"props":5570,"children":5571},{"style":643},[5572],{"type":57,"value":1235},{"type":48,"tag":103,"props":5574,"children":5575},{"style":709},[5576],{"type":57,"value":5462},{"type":48,"tag":103,"props":5578,"children":5579},{"style":649},[5580],{"type":57,"value":716},{"type":48,"tag":103,"props":5582,"children":5583},{"style":643},[5584],{"type":57,"value":1248},{"type":48,"tag":103,"props":5586,"children":5587},{"style":728},[5588],{"type":57,"value":5589}," noServer",{"type":48,"tag":103,"props":5591,"children":5592},{"style":643},[5593],{"type":57,"value":612},{"type":48,"tag":103,"props":5595,"children":5597},{"style":5596},"--shiki-light:#FF5370;--shiki-default:#FF9CAC;--shiki-dark:#FF9CAC",[5598],{"type":57,"value":5599}," true",{"type":48,"tag":103,"props":5601,"children":5602},{"style":643},[5603],{"type":57,"value":657},{"type":48,"tag":103,"props":5605,"children":5606},{"style":649},[5607],{"type":57,"value":894},{"type":48,"tag":103,"props":5609,"children":5610},{"style":643},[5611],{"type":57,"value":682},{"type":48,"tag":103,"props":5613,"children":5614},{"class":105,"line":777},[5615],{"type":48,"tag":103,"props":5616,"children":5617},{"emptyLinePlaceholder":689},[5618],{"type":57,"value":692},{"type":48,"tag":103,"props":5620,"children":5621},{"class":105,"line":786},[5622,5626,5630],{"type":48,"tag":103,"props":5623,"children":5624},{"style":637},[5625],{"type":57,"value":701},{"type":48,"tag":103,"props":5627,"children":5628},{"style":637},[5629],{"type":57,"value":706},{"type":48,"tag":103,"props":5631,"children":5632},{"style":643},[5633],{"type":57,"value":740},{"type":48,"tag":103,"props":5635,"children":5636},{"class":105,"line":822},[5637],{"type":48,"tag":103,"props":5638,"children":5639},{"style":627},[5640],{"type":57,"value":5641},"  \u002F\u002F Plain HTTP (health checks, REST) is handled by fetch.\n",{"type":48,"tag":103,"props":5643,"children":5644},{"class":105,"line":857},[5645,5649,5653,5658,5662,5666,5670,5674,5678,5683,5687,5691],{"type":48,"tag":103,"props":5646,"children":5647},{"style":709},[5648],{"type":57,"value":5154},{"type":48,"tag":103,"props":5650,"children":5651},{"style":643},[5652],{"type":57,"value":612},{"type":48,"tag":103,"props":5654,"children":5655},{"style":643},[5656],{"type":57,"value":5657}," ()",{"type":48,"tag":103,"props":5659,"children":5660},{"style":1188},[5661],{"type":57,"value":1438},{"type":48,"tag":103,"props":5663,"children":5664},{"style":643},[5665],{"type":57,"value":1235},{"type":48,"tag":103,"props":5667,"children":5668},{"style":709},[5669],{"type":57,"value":4368},{"type":48,"tag":103,"props":5671,"children":5672},{"style":649},[5673],{"type":57,"value":716},{"type":48,"tag":103,"props":5675,"children":5676},{"style":643},[5677],{"type":57,"value":677},{"type":48,"tag":103,"props":5679,"children":5680},{"style":116},[5681],{"type":57,"value":5682},"WebSocket endpoint — connect with ?token=\u003Cjwt>",{"type":48,"tag":103,"props":5684,"children":5685},{"style":643},[5686],{"type":57,"value":677},{"type":48,"tag":103,"props":5688,"children":5689},{"style":649},[5690],{"type":57,"value":894},{"type":48,"tag":103,"props":5692,"children":5693},{"style":643},[5694],{"type":57,"value":2770},{"type":48,"tag":103,"props":5696,"children":5697},{"class":105,"line":34},[5698],{"type":48,"tag":103,"props":5699,"children":5700},{"emptyLinePlaceholder":689},[5701],{"type":57,"value":692},{"type":48,"tag":103,"props":5703,"children":5704},{"class":105,"line":874},[5705],{"type":48,"tag":103,"props":5706,"children":5707},{"style":627},[5708],{"type":57,"value":5709},"  \u002F\u002F The runtime hands the WebSocket handshake to upgrade().\n",{"type":48,"tag":103,"props":5711,"children":5712},{"class":105,"line":883},[5713,5717,5721,5725,5729,5733,5737,5741,5745,5749,5753,5757,5761,5765,5769,5773],{"type":48,"tag":103,"props":5714,"children":5715},{"style":1188},[5716],{"type":57,"value":4276},{"type":48,"tag":103,"props":5718,"children":5719},{"style":728},[5720],{"type":57,"value":5227},{"type":48,"tag":103,"props":5722,"children":5723},{"style":643},[5724],{"type":57,"value":716},{"type":48,"tag":103,"props":5726,"children":5727},{"style":1426},[5728],{"type":57,"value":1585},{"type":48,"tag":103,"props":5730,"children":5731},{"style":643},[5732],{"type":57,"value":612},{"type":48,"tag":103,"props":5734,"children":5735},{"style":110},[5736],{"type":57,"value":5244},{"type":48,"tag":103,"props":5738,"children":5739},{"style":643},[5740],{"type":57,"value":814},{"type":48,"tag":103,"props":5742,"children":5743},{"style":1426},[5744],{"type":57,"value":5253},{"type":48,"tag":103,"props":5746,"children":5747},{"style":643},[5748],{"type":57,"value":612},{"type":48,"tag":103,"props":5750,"children":5751},{"style":110},[5752],{"type":57,"value":5262},{"type":48,"tag":103,"props":5754,"children":5755},{"style":643},[5756],{"type":57,"value":814},{"type":48,"tag":103,"props":5758,"children":5759},{"style":1426},[5760],{"type":57,"value":5271},{"type":48,"tag":103,"props":5762,"children":5763},{"style":643},[5764],{"type":57,"value":612},{"type":48,"tag":103,"props":5766,"children":5767},{"style":110},[5768],{"type":57,"value":5280},{"type":48,"tag":103,"props":5770,"children":5771},{"style":643},[5772],{"type":57,"value":894},{"type":48,"tag":103,"props":5774,"children":5775},{"style":643},[5776],{"type":57,"value":740},{"type":48,"tag":103,"props":5778,"children":5779},{"class":105,"line":1480},[5780,5784,5789,5793,5797,5801,5805,5809,5813,5818,5823,5827,5831,5835,5839,5843,5848,5852,5856],{"type":48,"tag":103,"props":5781,"children":5782},{"style":1188},[5783],{"type":57,"value":4451},{"type":48,"tag":103,"props":5785,"children":5786},{"style":649},[5787],{"type":57,"value":5788}," url",{"type":48,"tag":103,"props":5790,"children":5791},{"style":643},[5792],{"type":57,"value":1567},{"type":48,"tag":103,"props":5794,"children":5795},{"style":643},[5796],{"type":57,"value":1235},{"type":48,"tag":103,"props":5798,"children":5799},{"style":709},[5800],{"type":57,"value":4193},{"type":48,"tag":103,"props":5802,"children":5803},{"style":728},[5804],{"type":57,"value":716},{"type":48,"tag":103,"props":5806,"children":5807},{"style":649},[5808],{"type":57,"value":1585},{"type":48,"tag":103,"props":5810,"children":5811},{"style":643},[5812],{"type":57,"value":158},{"type":48,"tag":103,"props":5814,"children":5815},{"style":649},[5816],{"type":57,"value":5817},"url",{"type":48,"tag":103,"props":5819,"children":5820},{"style":643},[5821],{"type":57,"value":5822}," ??",{"type":48,"tag":103,"props":5824,"children":5825},{"style":643},[5826],{"type":57,"value":667},{"type":48,"tag":103,"props":5828,"children":5829},{"style":116},[5830],{"type":57,"value":1410},{"type":48,"tag":103,"props":5832,"children":5833},{"style":643},[5834],{"type":57,"value":677},{"type":48,"tag":103,"props":5836,"children":5837},{"style":643},[5838],{"type":57,"value":814},{"type":48,"tag":103,"props":5840,"children":5841},{"style":643},[5842],{"type":57,"value":667},{"type":48,"tag":103,"props":5844,"children":5845},{"style":116},[5846],{"type":57,"value":5847},"http:\u002F\u002Flocalhost",{"type":48,"tag":103,"props":5849,"children":5850},{"style":643},[5851],{"type":57,"value":677},{"type":48,"tag":103,"props":5853,"children":5854},{"style":728},[5855],{"type":57,"value":894},{"type":48,"tag":103,"props":5857,"children":5858},{"style":643},[5859],{"type":57,"value":682},{"type":48,"tag":103,"props":5861,"children":5862},{"class":105,"line":1543},[5863,5867,5872,5876,5880,5885,5889,5893,5897,5902,5906,5910,5914,5918,5923,5927,5931,5935],{"type":48,"tag":103,"props":5864,"children":5865},{"style":1188},[5866],{"type":57,"value":4451},{"type":48,"tag":103,"props":5868,"children":5869},{"style":649},[5870],{"type":57,"value":5871}," identity",{"type":48,"tag":103,"props":5873,"children":5874},{"style":643},[5875],{"type":57,"value":1567},{"type":48,"tag":103,"props":5877,"children":5878},{"style":637},[5879],{"type":57,"value":1572},{"type":48,"tag":103,"props":5881,"children":5882},{"style":709},[5883],{"type":57,"value":5884}," verifyToken",{"type":48,"tag":103,"props":5886,"children":5887},{"style":728},[5888],{"type":57,"value":716},{"type":48,"tag":103,"props":5890,"children":5891},{"style":649},[5892],{"type":57,"value":5817},{"type":48,"tag":103,"props":5894,"children":5895},{"style":643},[5896],{"type":57,"value":158},{"type":48,"tag":103,"props":5898,"children":5899},{"style":649},[5900],{"type":57,"value":5901},"searchParams",{"type":48,"tag":103,"props":5903,"children":5904},{"style":643},[5905],{"type":57,"value":158},{"type":48,"tag":103,"props":5907,"children":5908},{"style":709},[5909],{"type":57,"value":1397},{"type":48,"tag":103,"props":5911,"children":5912},{"style":728},[5913],{"type":57,"value":716},{"type":48,"tag":103,"props":5915,"children":5916},{"style":643},[5917],{"type":57,"value":677},{"type":48,"tag":103,"props":5919,"children":5920},{"style":116},[5921],{"type":57,"value":5922},"token",{"type":48,"tag":103,"props":5924,"children":5925},{"style":643},[5926],{"type":57,"value":677},{"type":48,"tag":103,"props":5928,"children":5929},{"style":728},[5930],{"type":57,"value":1473},{"type":48,"tag":103,"props":5932,"children":5933},{"style":643},[5934],{"type":57,"value":2054},{"type":48,"tag":103,"props":5936,"children":5937},{"style":627},[5938],{"type":57,"value":5939}," \u002F\u002F reject if invalid\n",{"type":48,"tag":103,"props":5941,"children":5942},{"class":105,"line":1628},[5943,5947,5951,5955,5960,5964],{"type":48,"tag":103,"props":5944,"children":5945},{"style":637},[5946],{"type":57,"value":4315},{"type":48,"tag":103,"props":5948,"children":5949},{"style":728},[5950],{"type":57,"value":1423},{"type":48,"tag":103,"props":5952,"children":5953},{"style":643},[5954],{"type":57,"value":3215},{"type":48,"tag":103,"props":5956,"children":5957},{"style":649},[5958],{"type":57,"value":5959},"identity",{"type":48,"tag":103,"props":5961,"children":5962},{"style":728},[5963],{"type":57,"value":4354},{"type":48,"tag":103,"props":5965,"children":5966},{"style":643},[5967],{"type":57,"value":721},{"type":48,"tag":103,"props":5969,"children":5970},{"class":105,"line":1732},[5971,5976,5980,5985,5989,5993,5998,6003,6007,6011],{"type":48,"tag":103,"props":5972,"children":5973},{"style":649},[5974],{"type":57,"value":5975},"      socket",{"type":48,"tag":103,"props":5977,"children":5978},{"style":643},[5979],{"type":57,"value":158},{"type":48,"tag":103,"props":5981,"children":5982},{"style":709},[5983],{"type":57,"value":5984},"write",{"type":48,"tag":103,"props":5986,"children":5987},{"style":728},[5988],{"type":57,"value":716},{"type":48,"tag":103,"props":5990,"children":5991},{"style":643},[5992],{"type":57,"value":677},{"type":48,"tag":103,"props":5994,"children":5995},{"style":116},[5996],{"type":57,"value":5997},"HTTP\u002F1.1 401 Unauthorized",{"type":48,"tag":103,"props":5999,"children":6000},{"style":649},[6001],{"type":57,"value":6002},"\\r\\n\\r\\n",{"type":48,"tag":103,"props":6004,"children":6005},{"style":643},[6006],{"type":57,"value":677},{"type":48,"tag":103,"props":6008,"children":6009},{"style":728},[6010],{"type":57,"value":894},{"type":48,"tag":103,"props":6012,"children":6013},{"style":643},[6014],{"type":57,"value":682},{"type":48,"tag":103,"props":6016,"children":6017},{"class":105,"line":1778},[6018,6022,6026,6031,6035],{"type":48,"tag":103,"props":6019,"children":6020},{"style":649},[6021],{"type":57,"value":5975},{"type":48,"tag":103,"props":6023,"children":6024},{"style":643},[6025],{"type":57,"value":158},{"type":48,"tag":103,"props":6027,"children":6028},{"style":709},[6029],{"type":57,"value":6030},"destroy",{"type":48,"tag":103,"props":6032,"children":6033},{"style":728},[6034],{"type":57,"value":1376},{"type":48,"tag":103,"props":6036,"children":6037},{"style":643},[6038],{"type":57,"value":682},{"type":48,"tag":103,"props":6040,"children":6041},{"class":105,"line":1794},[6042,6046],{"type":48,"tag":103,"props":6043,"children":6044},{"style":637},[6045],{"type":57,"value":4584},{"type":48,"tag":103,"props":6047,"children":6048},{"style":643},[6049],{"type":57,"value":682},{"type":48,"tag":103,"props":6051,"children":6052},{"class":105,"line":1905},[6053],{"type":48,"tag":103,"props":6054,"children":6055},{"style":643},[6056],{"type":57,"value":4678},{"type":48,"tag":103,"props":6058,"children":6059},{"class":105,"line":1913},[6060,6065,6069,6074,6078,6082,6086,6090,6094,6098,6102,6106,6110,6114,6118],{"type":48,"tag":103,"props":6061,"children":6062},{"style":649},[6063],{"type":57,"value":6064},"    wss",{"type":48,"tag":103,"props":6066,"children":6067},{"style":643},[6068],{"type":57,"value":158},{"type":48,"tag":103,"props":6070,"children":6071},{"style":709},[6072],{"type":57,"value":6073},"handleUpgrade",{"type":48,"tag":103,"props":6075,"children":6076},{"style":728},[6077],{"type":57,"value":716},{"type":48,"tag":103,"props":6079,"children":6080},{"style":649},[6081],{"type":57,"value":1585},{"type":48,"tag":103,"props":6083,"children":6084},{"style":643},[6085],{"type":57,"value":814},{"type":48,"tag":103,"props":6087,"children":6088},{"style":649},[6089],{"type":57,"value":5253},{"type":48,"tag":103,"props":6091,"children":6092},{"style":643},[6093],{"type":57,"value":814},{"type":48,"tag":103,"props":6095,"children":6096},{"style":649},[6097],{"type":57,"value":5271},{"type":48,"tag":103,"props":6099,"children":6100},{"style":643},[6101],{"type":57,"value":814},{"type":48,"tag":103,"props":6103,"children":6104},{"style":643},[6105],{"type":57,"value":1423},{"type":48,"tag":103,"props":6107,"children":6108},{"style":1426},[6109],{"type":57,"value":5077},{"type":48,"tag":103,"props":6111,"children":6112},{"style":643},[6113],{"type":57,"value":894},{"type":48,"tag":103,"props":6115,"children":6116},{"style":1188},[6117],{"type":57,"value":1438},{"type":48,"tag":103,"props":6119,"children":6120},{"style":643},[6121],{"type":57,"value":740},{"type":48,"tag":103,"props":6123,"children":6124},{"class":105,"line":5015},[6125,6130,6134,6139,6143,6147,6151],{"type":48,"tag":103,"props":6126,"children":6127},{"style":649},[6128],{"type":57,"value":6129},"      clients",{"type":48,"tag":103,"props":6131,"children":6132},{"style":643},[6133],{"type":57,"value":158},{"type":48,"tag":103,"props":6135,"children":6136},{"style":709},[6137],{"type":57,"value":6138},"add",{"type":48,"tag":103,"props":6140,"children":6141},{"style":728},[6142],{"type":57,"value":716},{"type":48,"tag":103,"props":6144,"children":6145},{"style":649},[6146],{"type":57,"value":5077},{"type":48,"tag":103,"props":6148,"children":6149},{"style":728},[6150],{"type":57,"value":894},{"type":48,"tag":103,"props":6152,"children":6153},{"style":643},[6154],{"type":57,"value":682},{"type":48,"tag":103,"props":6156,"children":6157},{"class":105,"line":5023},[6158,6163,6167,6172,6176,6180,6185,6189,6193,6197,6201,6206,6210,6215,6219,6223,6227],{"type":48,"tag":103,"props":6159,"children":6160},{"style":649},[6161],{"type":57,"value":6162},"      ws",{"type":48,"tag":103,"props":6164,"children":6165},{"style":643},[6166],{"type":57,"value":158},{"type":48,"tag":103,"props":6168,"children":6169},{"style":709},[6170],{"type":57,"value":6171},"on",{"type":48,"tag":103,"props":6173,"children":6174},{"style":728},[6175],{"type":57,"value":716},{"type":48,"tag":103,"props":6177,"children":6178},{"style":643},[6179],{"type":57,"value":677},{"type":48,"tag":103,"props":6181,"children":6182},{"style":116},[6183],{"type":57,"value":6184},"close",{"type":48,"tag":103,"props":6186,"children":6187},{"style":643},[6188],{"type":57,"value":677},{"type":48,"tag":103,"props":6190,"children":6191},{"style":643},[6192],{"type":57,"value":814},{"type":48,"tag":103,"props":6194,"children":6195},{"style":643},[6196],{"type":57,"value":5657},{"type":48,"tag":103,"props":6198,"children":6199},{"style":1188},[6200],{"type":57,"value":1438},{"type":48,"tag":103,"props":6202,"children":6203},{"style":649},[6204],{"type":57,"value":6205}," clients",{"type":48,"tag":103,"props":6207,"children":6208},{"style":643},[6209],{"type":57,"value":158},{"type":48,"tag":103,"props":6211,"children":6212},{"style":709},[6213],{"type":57,"value":6214},"delete",{"type":48,"tag":103,"props":6216,"children":6217},{"style":728},[6218],{"type":57,"value":716},{"type":48,"tag":103,"props":6220,"children":6221},{"style":649},[6222],{"type":57,"value":5077},{"type":48,"tag":103,"props":6224,"children":6225},{"style":728},[6226],{"type":57,"value":1473},{"type":48,"tag":103,"props":6228,"children":6229},{"style":643},[6230],{"type":57,"value":682},{"type":48,"tag":103,"props":6232,"children":6233},{"class":105,"line":5031},[6234,6238,6242,6246,6250,6254,6259,6263,6267,6271,6276,6280,6284,6289,6293,6297,6301,6306,6311,6315],{"type":48,"tag":103,"props":6235,"children":6236},{"style":649},[6237],{"type":57,"value":6162},{"type":48,"tag":103,"props":6239,"children":6240},{"style":643},[6241],{"type":57,"value":158},{"type":48,"tag":103,"props":6243,"children":6244},{"style":709},[6245],{"type":57,"value":6171},{"type":48,"tag":103,"props":6247,"children":6248},{"style":728},[6249],{"type":57,"value":716},{"type":48,"tag":103,"props":6251,"children":6252},{"style":643},[6253],{"type":57,"value":677},{"type":48,"tag":103,"props":6255,"children":6256},{"style":116},[6257],{"type":57,"value":6258},"message",{"type":48,"tag":103,"props":6260,"children":6261},{"style":643},[6262],{"type":57,"value":677},{"type":48,"tag":103,"props":6264,"children":6265},{"style":643},[6266],{"type":57,"value":814},{"type":48,"tag":103,"props":6268,"children":6269},{"style":643},[6270],{"type":57,"value":1423},{"type":48,"tag":103,"props":6272,"children":6273},{"style":1426},[6274],{"type":57,"value":6275},"data",{"type":48,"tag":103,"props":6277,"children":6278},{"style":643},[6279],{"type":57,"value":894},{"type":48,"tag":103,"props":6281,"children":6282},{"style":1188},[6283],{"type":57,"value":1438},{"type":48,"tag":103,"props":6285,"children":6286},{"style":709},[6287],{"type":57,"value":6288}," persist",{"type":48,"tag":103,"props":6290,"children":6291},{"style":728},[6292],{"type":57,"value":716},{"type":48,"tag":103,"props":6294,"children":6295},{"style":649},[6296],{"type":57,"value":6275},{"type":48,"tag":103,"props":6298,"children":6299},{"style":643},[6300],{"type":57,"value":158},{"type":48,"tag":103,"props":6302,"children":6303},{"style":709},[6304],{"type":57,"value":6305},"toString",{"type":48,"tag":103,"props":6307,"children":6308},{"style":728},[6309],{"type":57,"value":6310},"()))",{"type":48,"tag":103,"props":6312,"children":6313},{"style":643},[6314],{"type":57,"value":2054},{"type":48,"tag":103,"props":6316,"children":6317},{"style":627},[6318],{"type":57,"value":6319}," \u002F\u002F persist; fan out to every isolate — see below\n",{"type":48,"tag":103,"props":6321,"children":6323},{"class":105,"line":6322},26,[6324,6328,6332],{"type":48,"tag":103,"props":6325,"children":6326},{"style":643},[6327],{"type":57,"value":4912},{"type":48,"tag":103,"props":6329,"children":6330},{"style":728},[6331],{"type":57,"value":894},{"type":48,"tag":103,"props":6333,"children":6334},{"style":643},[6335],{"type":57,"value":682},{"type":48,"tag":103,"props":6337,"children":6339},{"class":105,"line":6338},27,[6340],{"type":48,"tag":103,"props":6341,"children":6342},{"style":643},[6343],{"type":57,"value":880},{"type":48,"tag":103,"props":6345,"children":6347},{"class":105,"line":6346},28,[6348],{"type":48,"tag":103,"props":6349,"children":6350},{"style":643},[6351],{"type":57,"value":5037},{"type":48,"tag":49,"props":6353,"children":6354},{},[6355,6360,6362,6367,6369,6374,6376,6382,6384,6389,6391,6396],{"type":48,"tag":53,"props":6356,"children":6357},{},[6358],{"type":57,"value":6359},"Hono variant.",{"type":57,"value":6361}," If you only need Hono for the HTTP side and are happy driving ",{"type":48,"tag":62,"props":6363,"children":6365},{"className":6364},[],[6366],{"type":57,"value":5077},{"type":57,"value":6368}," yourself, just swap ",{"type":48,"tag":62,"props":6370,"children":6372},{"className":6371},[],[6373],{"type":57,"value":4016},{"type":57,"value":6375}," in the simple example for ",{"type":48,"tag":62,"props":6377,"children":6379},{"className":6378},[],[6380],{"type":57,"value":6381},"app.fetch",{"type":57,"value":6383}," and keep the raw ",{"type":48,"tag":62,"props":6385,"children":6387},{"className":6386},[],[6388],{"type":57,"value":5109},{"type":57,"value":6390}," — Hono serves routing\u002Fmiddleware, ",{"type":48,"tag":62,"props":6392,"children":6394},{"className":6393},[],[6395],{"type":57,"value":5077},{"type":57,"value":6397}," serves the socket.",{"type":48,"tag":49,"props":6399,"children":6400},{},[6401,6403,6408,6410,6416,6418,6424,6425,6431,6432,6438,6440,6446,6448,6454,6456,6461,6463,6469,6471,6478,6480,6486,6488,6493,6494,6499,6501,6506,6508,6514,6516,6522,6523,6528],{"type":57,"value":6402},"To instead declare WebSocket routes ",{"type":48,"tag":221,"props":6404,"children":6405},{},[6406],{"type":57,"value":6407},"inside",{"type":57,"value":6409}," the Hono app — ",{"type":48,"tag":62,"props":6411,"children":6413},{"className":6412},[],[6414],{"type":57,"value":6415},"app.get(\"\u002Fws\", upgradeWebSocket(...))",{"type":57,"value":6417}," with the standard ",{"type":48,"tag":62,"props":6419,"children":6421},{"className":6420},[],[6422],{"type":57,"value":6423},"onOpen",{"type":57,"value":1410},{"type":48,"tag":62,"props":6426,"children":6428},{"className":6427},[],[6429],{"type":57,"value":6430},"onMessage",{"type":57,"value":1410},{"type":48,"tag":62,"props":6433,"children":6435},{"className":6434},[],[6436],{"type":57,"value":6437},"onClose",{"type":57,"value":6439}," lifecycle — you need an adapter that bridges Hono's ",{"type":48,"tag":62,"props":6441,"children":6443},{"className":6442},[],[6444],{"type":57,"value":6445},"upgradeWebSocket()",{"type":57,"value":6447}," helper to Neon's ",{"type":48,"tag":62,"props":6449,"children":6451},{"className":6450},[],[6452],{"type":57,"value":6453},"upgrade(req, socket, head)",{"type":57,"value":6455},". Hono ships adapters for Cloudflare\u002FDeno\u002FBun\u002FNode, but ",{"type":48,"tag":53,"props":6457,"children":6458},{},[6459],{"type":57,"value":6460},"none for Neon",{"type":57,"value":6462},", and the Node one (",{"type":48,"tag":62,"props":6464,"children":6466},{"className":6465},[],[6467],{"type":57,"value":6468},"@hono\u002Fnode-ws",{"type":57,"value":6470},") is deprecated and assumes it owns the HTTP server. ",{"type":48,"tag":82,"props":6472,"children":6475},{"href":6473,"rel":6474},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fhono-websockets.md",[86],[6476],{"type":57,"value":6477},"references\u002Fhono-websockets.md",{"type":57,"value":6479}," has a small self-contained ",{"type":48,"tag":62,"props":6481,"children":6483},{"className":6482},[],[6484],{"type":57,"value":6485},"createNeonWebSocket(app)",{"type":57,"value":6487}," adapter to copy in — it depends only on ",{"type":48,"tag":62,"props":6489,"children":6491},{"className":6490},[],[6492],{"type":57,"value":970},{"type":57,"value":310},{"type":48,"tag":62,"props":6495,"children":6497},{"className":6496},[],[6498],{"type":57,"value":5077},{"type":57,"value":6500}," (no deprecated package; adapted from ",{"type":48,"tag":62,"props":6502,"children":6504},{"className":6503},[],[6505],{"type":57,"value":6468},{"type":57,"value":6507},", MIT) and returns a ready-to-export ",{"type":48,"tag":62,"props":6509,"children":6511},{"className":6510},[],[6512],{"type":57,"value":6513},"{ fetch, upgrade }",{"type":57,"value":6515}," handler. Usage is idiomatic Hono, and because the handshake routes through ",{"type":48,"tag":62,"props":6517,"children":6519},{"className":6518},[],[6520],{"type":57,"value":6521},"app.request",{"type":57,"value":431},{"type":48,"tag":53,"props":6524,"children":6525},{},[6526],{"type":57,"value":6527},"auth is just normal route middleware",{"type":57,"value":612},{"type":48,"tag":92,"props":6530,"children":6532},{"className":615,"code":6531,"language":617,"meta":97,"style":97},"\u002F\u002F src\u002Findex.ts\nimport { Hono } from \"hono\";\nimport { createNeonWebSocket } from \".\u002Fhono-ws\";\n\nconst app = new Hono();\nconst { upgradeWebSocket, handler } = createNeonWebSocket(app);\n\napp.get(\n  \"\u002Fws\",\n  async (c, next) => {\n    if (!(await verifyToken(c.req.query(\"token\")))) return c.text(\"Unauthorized\", 401);\n    await next();\n  },\n  upgradeWebSocket(() => ({\n    onOpen: (_evt, ws) => ws.send(\"welcome\"),\n    onMessage: (evt, ws) => ws.send(`echo: ${evt.data}`),\n    onClose: () => console.log(\"disconnected\"),\n  })),\n);\n\nexport default handler; \u002F\u002F Neon's { fetch, upgrade } contract\n",[6533],{"type":48,"tag":62,"props":6534,"children":6535},{"__ignoreMap":97},[6536,6543,6582,6623,6630,6661,6707,6714,6734,6755,6791,6912,6932,6939,6967,7043,7135,7194,7209,7220,7227],{"type":48,"tag":103,"props":6537,"children":6538},{"class":105,"line":106},[6539],{"type":48,"tag":103,"props":6540,"children":6541},{"style":627},[6542],{"type":57,"value":937},{"type":48,"tag":103,"props":6544,"children":6545},{"class":105,"line":633},[6546,6550,6554,6558,6562,6566,6570,6574,6578],{"type":48,"tag":103,"props":6547,"children":6548},{"style":637},[6549],{"type":57,"value":640},{"type":48,"tag":103,"props":6551,"children":6552},{"style":643},[6553],{"type":57,"value":646},{"type":48,"tag":103,"props":6555,"children":6556},{"style":649},[6557],{"type":57,"value":953},{"type":48,"tag":103,"props":6559,"children":6560},{"style":643},[6561],{"type":57,"value":657},{"type":48,"tag":103,"props":6563,"children":6564},{"style":637},[6565],{"type":57,"value":662},{"type":48,"tag":103,"props":6567,"children":6568},{"style":643},[6569],{"type":57,"value":667},{"type":48,"tag":103,"props":6571,"children":6572},{"style":116},[6573],{"type":57,"value":970},{"type":48,"tag":103,"props":6575,"children":6576},{"style":643},[6577],{"type":57,"value":677},{"type":48,"tag":103,"props":6579,"children":6580},{"style":643},[6581],{"type":57,"value":682},{"type":48,"tag":103,"props":6583,"children":6584},{"class":105,"line":685},[6585,6589,6593,6598,6602,6606,6610,6615,6619],{"type":48,"tag":103,"props":6586,"children":6587},{"style":637},[6588],{"type":57,"value":640},{"type":48,"tag":103,"props":6590,"children":6591},{"style":643},[6592],{"type":57,"value":646},{"type":48,"tag":103,"props":6594,"children":6595},{"style":649},[6596],{"type":57,"value":6597}," createNeonWebSocket",{"type":48,"tag":103,"props":6599,"children":6600},{"style":643},[6601],{"type":57,"value":657},{"type":48,"tag":103,"props":6603,"children":6604},{"style":637},[6605],{"type":57,"value":662},{"type":48,"tag":103,"props":6607,"children":6608},{"style":643},[6609],{"type":57,"value":667},{"type":48,"tag":103,"props":6611,"children":6612},{"style":116},[6613],{"type":57,"value":6614},".\u002Fhono-ws",{"type":48,"tag":103,"props":6616,"children":6617},{"style":643},[6618],{"type":57,"value":677},{"type":48,"tag":103,"props":6620,"children":6621},{"style":643},[6622],{"type":57,"value":682},{"type":48,"tag":103,"props":6624,"children":6625},{"class":105,"line":695},[6626],{"type":48,"tag":103,"props":6627,"children":6628},{"emptyLinePlaceholder":689},[6629],{"type":57,"value":692},{"type":48,"tag":103,"props":6631,"children":6632},{"class":105,"line":724},[6633,6637,6641,6645,6649,6653,6657],{"type":48,"tag":103,"props":6634,"children":6635},{"style":1188},[6636],{"type":57,"value":1191},{"type":48,"tag":103,"props":6638,"children":6639},{"style":649},[6640],{"type":57,"value":1359},{"type":48,"tag":103,"props":6642,"children":6643},{"style":643},[6644],{"type":57,"value":1201},{"type":48,"tag":103,"props":6646,"children":6647},{"style":643},[6648],{"type":57,"value":1235},{"type":48,"tag":103,"props":6650,"children":6651},{"style":709},[6652],{"type":57,"value":953},{"type":48,"tag":103,"props":6654,"children":6655},{"style":649},[6656],{"type":57,"value":1376},{"type":48,"tag":103,"props":6658,"children":6659},{"style":643},[6660],{"type":57,"value":682},{"type":48,"tag":103,"props":6662,"children":6663},{"class":105,"line":743},[6664,6668,6672,6677,6681,6686,6690,6694,6698,6703],{"type":48,"tag":103,"props":6665,"children":6666},{"style":1188},[6667],{"type":57,"value":1191},{"type":48,"tag":103,"props":6669,"children":6670},{"style":643},[6671],{"type":57,"value":646},{"type":48,"tag":103,"props":6673,"children":6674},{"style":649},[6675],{"type":57,"value":6676}," upgradeWebSocket",{"type":48,"tag":103,"props":6678,"children":6679},{"style":643},[6680],{"type":57,"value":814},{"type":48,"tag":103,"props":6682,"children":6683},{"style":649},[6684],{"type":57,"value":6685}," handler ",{"type":48,"tag":103,"props":6687,"children":6688},{"style":643},[6689],{"type":57,"value":889},{"type":48,"tag":103,"props":6691,"children":6692},{"style":643},[6693],{"type":57,"value":1567},{"type":48,"tag":103,"props":6695,"children":6696},{"style":709},[6697],{"type":57,"value":6597},{"type":48,"tag":103,"props":6699,"children":6700},{"style":649},[6701],{"type":57,"value":6702},"(app)",{"type":48,"tag":103,"props":6704,"children":6705},{"style":643},[6706],{"type":57,"value":682},{"type":48,"tag":103,"props":6708,"children":6709},{"class":105,"line":760},[6710],{"type":48,"tag":103,"props":6711,"children":6712},{"emptyLinePlaceholder":689},[6713],{"type":57,"value":692},{"type":48,"tag":103,"props":6715,"children":6716},{"class":105,"line":777},[6717,6721,6725,6729],{"type":48,"tag":103,"props":6718,"children":6719},{"style":649},[6720],{"type":57,"value":1388},{"type":48,"tag":103,"props":6722,"children":6723},{"style":643},[6724],{"type":57,"value":158},{"type":48,"tag":103,"props":6726,"children":6727},{"style":709},[6728],{"type":57,"value":1397},{"type":48,"tag":103,"props":6730,"children":6731},{"style":649},[6732],{"type":57,"value":6733},"(\n",{"type":48,"tag":103,"props":6735,"children":6736},{"class":105,"line":786},[6737,6742,6747,6751],{"type":48,"tag":103,"props":6738,"children":6739},{"style":643},[6740],{"type":57,"value":6741},"  \"",{"type":48,"tag":103,"props":6743,"children":6744},{"style":116},[6745],{"type":57,"value":6746},"\u002Fws",{"type":48,"tag":103,"props":6748,"children":6749},{"style":643},[6750],{"type":57,"value":677},{"type":48,"tag":103,"props":6752,"children":6753},{"style":643},[6754],{"type":57,"value":2770},{"type":48,"tag":103,"props":6756,"children":6757},{"class":105,"line":822},[6758,6762,6766,6770,6774,6779,6783,6787],{"type":48,"tag":103,"props":6759,"children":6760},{"style":1188},[6761],{"type":57,"value":4276},{"type":48,"tag":103,"props":6763,"children":6764},{"style":643},[6765],{"type":57,"value":1423},{"type":48,"tag":103,"props":6767,"children":6768},{"style":1426},[6769],{"type":57,"value":1429},{"type":48,"tag":103,"props":6771,"children":6772},{"style":643},[6773],{"type":57,"value":814},{"type":48,"tag":103,"props":6775,"children":6776},{"style":1426},[6777],{"type":57,"value":6778}," next",{"type":48,"tag":103,"props":6780,"children":6781},{"style":643},[6782],{"type":57,"value":894},{"type":48,"tag":103,"props":6784,"children":6785},{"style":1188},[6786],{"type":57,"value":1438},{"type":48,"tag":103,"props":6788,"children":6789},{"style":643},[6790],{"type":57,"value":740},{"type":48,"tag":103,"props":6792,"children":6793},{"class":105,"line":857},[6794,6798,6802,6806,6810,6814,6818,6822,6826,6830,6834,6838,6843,6847,6851,6855,6859,6864,6868,6872,6876,6880,6884,6888,6892,6896,6900,6904,6908],{"type":48,"tag":103,"props":6795,"children":6796},{"style":637},[6797],{"type":57,"value":4315},{"type":48,"tag":103,"props":6799,"children":6800},{"style":728},[6801],{"type":57,"value":1423},{"type":48,"tag":103,"props":6803,"children":6804},{"style":643},[6805],{"type":57,"value":3215},{"type":48,"tag":103,"props":6807,"children":6808},{"style":728},[6809],{"type":57,"value":716},{"type":48,"tag":103,"props":6811,"children":6812},{"style":637},[6813],{"type":57,"value":1868},{"type":48,"tag":103,"props":6815,"children":6816},{"style":709},[6817],{"type":57,"value":5884},{"type":48,"tag":103,"props":6819,"children":6820},{"style":728},[6821],{"type":57,"value":716},{"type":48,"tag":103,"props":6823,"children":6824},{"style":649},[6825],{"type":57,"value":1429},{"type":48,"tag":103,"props":6827,"children":6828},{"style":643},[6829],{"type":57,"value":158},{"type":48,"tag":103,"props":6831,"children":6832},{"style":649},[6833],{"type":57,"value":1585},{"type":48,"tag":103,"props":6835,"children":6836},{"style":643},[6837],{"type":57,"value":158},{"type":48,"tag":103,"props":6839,"children":6840},{"style":709},[6841],{"type":57,"value":6842},"query",{"type":48,"tag":103,"props":6844,"children":6845},{"style":728},[6846],{"type":57,"value":716},{"type":48,"tag":103,"props":6848,"children":6849},{"style":643},[6850],{"type":57,"value":677},{"type":48,"tag":103,"props":6852,"children":6853},{"style":116},[6854],{"type":57,"value":5922},{"type":48,"tag":103,"props":6856,"children":6857},{"style":643},[6858],{"type":57,"value":677},{"type":48,"tag":103,"props":6860,"children":6861},{"style":728},[6862],{"type":57,"value":6863},")))) ",{"type":48,"tag":103,"props":6865,"children":6866},{"style":637},[6867],{"type":57,"value":4359},{"type":48,"tag":103,"props":6869,"children":6870},{"style":649},[6871],{"type":57,"value":1443},{"type":48,"tag":103,"props":6873,"children":6874},{"style":643},[6875],{"type":57,"value":158},{"type":48,"tag":103,"props":6877,"children":6878},{"style":709},[6879],{"type":57,"value":57},{"type":48,"tag":103,"props":6881,"children":6882},{"style":728},[6883],{"type":57,"value":716},{"type":48,"tag":103,"props":6885,"children":6886},{"style":643},[6887],{"type":57,"value":677},{"type":48,"tag":103,"props":6889,"children":6890},{"style":116},[6891],{"type":57,"value":4605},{"type":48,"tag":103,"props":6893,"children":6894},{"style":643},[6895],{"type":57,"value":677},{"type":48,"tag":103,"props":6897,"children":6898},{"style":643},[6899],{"type":57,"value":814},{"type":48,"tag":103,"props":6901,"children":6902},{"style":1296},[6903],{"type":57,"value":4630},{"type":48,"tag":103,"props":6905,"children":6906},{"style":728},[6907],{"type":57,"value":894},{"type":48,"tag":103,"props":6909,"children":6910},{"style":643},[6911],{"type":57,"value":682},{"type":48,"tag":103,"props":6913,"children":6914},{"class":105,"line":34},[6915,6920,6924,6928],{"type":48,"tag":103,"props":6916,"children":6917},{"style":637},[6918],{"type":57,"value":6919},"    await",{"type":48,"tag":103,"props":6921,"children":6922},{"style":709},[6923],{"type":57,"value":6778},{"type":48,"tag":103,"props":6925,"children":6926},{"style":728},[6927],{"type":57,"value":1376},{"type":48,"tag":103,"props":6929,"children":6930},{"style":643},[6931],{"type":57,"value":682},{"type":48,"tag":103,"props":6933,"children":6934},{"class":105,"line":874},[6935],{"type":48,"tag":103,"props":6936,"children":6937},{"style":643},[6938],{"type":57,"value":880},{"type":48,"tag":103,"props":6940,"children":6941},{"class":105,"line":883},[6942,6947,6951,6955,6959,6963],{"type":48,"tag":103,"props":6943,"children":6944},{"style":709},[6945],{"type":57,"value":6946},"  upgradeWebSocket",{"type":48,"tag":103,"props":6948,"children":6949},{"style":649},[6950],{"type":57,"value":716},{"type":48,"tag":103,"props":6952,"children":6953},{"style":643},[6954],{"type":57,"value":1376},{"type":48,"tag":103,"props":6956,"children":6957},{"style":1188},[6958],{"type":57,"value":1438},{"type":48,"tag":103,"props":6960,"children":6961},{"style":649},[6962],{"type":57,"value":1423},{"type":48,"tag":103,"props":6964,"children":6965},{"style":643},[6966],{"type":57,"value":721},{"type":48,"tag":103,"props":6968,"children":6969},{"class":105,"line":1480},[6970,6975,6979,6983,6988,6992,6997,7001,7005,7009,7013,7018,7022,7026,7031,7035,7039],{"type":48,"tag":103,"props":6971,"children":6972},{"style":709},[6973],{"type":57,"value":6974},"    onOpen",{"type":48,"tag":103,"props":6976,"children":6977},{"style":643},[6978],{"type":57,"value":612},{"type":48,"tag":103,"props":6980,"children":6981},{"style":643},[6982],{"type":57,"value":1423},{"type":48,"tag":103,"props":6984,"children":6985},{"style":1426},[6986],{"type":57,"value":6987},"_evt",{"type":48,"tag":103,"props":6989,"children":6990},{"style":643},[6991],{"type":57,"value":814},{"type":48,"tag":103,"props":6993,"children":6994},{"style":1426},[6995],{"type":57,"value":6996}," ws",{"type":48,"tag":103,"props":6998,"children":6999},{"style":643},[7000],{"type":57,"value":894},{"type":48,"tag":103,"props":7002,"children":7003},{"style":1188},[7004],{"type":57,"value":1438},{"type":48,"tag":103,"props":7006,"children":7007},{"style":649},[7008],{"type":57,"value":6996},{"type":48,"tag":103,"props":7010,"children":7011},{"style":643},[7012],{"type":57,"value":158},{"type":48,"tag":103,"props":7014,"children":7015},{"style":709},[7016],{"type":57,"value":7017},"send",{"type":48,"tag":103,"props":7019,"children":7020},{"style":649},[7021],{"type":57,"value":716},{"type":48,"tag":103,"props":7023,"children":7024},{"style":643},[7025],{"type":57,"value":677},{"type":48,"tag":103,"props":7027,"children":7028},{"style":116},[7029],{"type":57,"value":7030},"welcome",{"type":48,"tag":103,"props":7032,"children":7033},{"style":643},[7034],{"type":57,"value":677},{"type":48,"tag":103,"props":7036,"children":7037},{"style":649},[7038],{"type":57,"value":894},{"type":48,"tag":103,"props":7040,"children":7041},{"style":643},[7042],{"type":57,"value":2770},{"type":48,"tag":103,"props":7044,"children":7045},{"class":105,"line":1543},[7046,7051,7055,7059,7064,7068,7072,7076,7080,7084,7088,7092,7096,7100,7105,7110,7114,7118,7122,7127,7131],{"type":48,"tag":103,"props":7047,"children":7048},{"style":709},[7049],{"type":57,"value":7050},"    onMessage",{"type":48,"tag":103,"props":7052,"children":7053},{"style":643},[7054],{"type":57,"value":612},{"type":48,"tag":103,"props":7056,"children":7057},{"style":643},[7058],{"type":57,"value":1423},{"type":48,"tag":103,"props":7060,"children":7061},{"style":1426},[7062],{"type":57,"value":7063},"evt",{"type":48,"tag":103,"props":7065,"children":7066},{"style":643},[7067],{"type":57,"value":814},{"type":48,"tag":103,"props":7069,"children":7070},{"style":1426},[7071],{"type":57,"value":6996},{"type":48,"tag":103,"props":7073,"children":7074},{"style":643},[7075],{"type":57,"value":894},{"type":48,"tag":103,"props":7077,"children":7078},{"style":1188},[7079],{"type":57,"value":1438},{"type":48,"tag":103,"props":7081,"children":7082},{"style":649},[7083],{"type":57,"value":6996},{"type":48,"tag":103,"props":7085,"children":7086},{"style":643},[7087],{"type":57,"value":158},{"type":48,"tag":103,"props":7089,"children":7090},{"style":709},[7091],{"type":57,"value":7017},{"type":48,"tag":103,"props":7093,"children":7094},{"style":649},[7095],{"type":57,"value":716},{"type":48,"tag":103,"props":7097,"children":7098},{"style":643},[7099],{"type":57,"value":4238},{"type":48,"tag":103,"props":7101,"children":7102},{"style":116},[7103],{"type":57,"value":7104},"echo: ",{"type":48,"tag":103,"props":7106,"children":7107},{"style":643},[7108],{"type":57,"value":7109},"${",{"type":48,"tag":103,"props":7111,"children":7112},{"style":649},[7113],{"type":57,"value":7063},{"type":48,"tag":103,"props":7115,"children":7116},{"style":643},[7117],{"type":57,"value":158},{"type":48,"tag":103,"props":7119,"children":7120},{"style":649},[7121],{"type":57,"value":6275},{"type":48,"tag":103,"props":7123,"children":7124},{"style":643},[7125],{"type":57,"value":7126},"}`",{"type":48,"tag":103,"props":7128,"children":7129},{"style":649},[7130],{"type":57,"value":894},{"type":48,"tag":103,"props":7132,"children":7133},{"style":643},[7134],{"type":57,"value":2770},{"type":48,"tag":103,"props":7136,"children":7137},{"class":105,"line":1628},[7138,7143,7147,7151,7155,7160,7164,7169,7173,7177,7182,7186,7190],{"type":48,"tag":103,"props":7139,"children":7140},{"style":709},[7141],{"type":57,"value":7142},"    onClose",{"type":48,"tag":103,"props":7144,"children":7145},{"style":643},[7146],{"type":57,"value":612},{"type":48,"tag":103,"props":7148,"children":7149},{"style":643},[7150],{"type":57,"value":5657},{"type":48,"tag":103,"props":7152,"children":7153},{"style":1188},[7154],{"type":57,"value":1438},{"type":48,"tag":103,"props":7156,"children":7157},{"style":649},[7158],{"type":57,"value":7159}," console",{"type":48,"tag":103,"props":7161,"children":7162},{"style":643},[7163],{"type":57,"value":158},{"type":48,"tag":103,"props":7165,"children":7166},{"style":709},[7167],{"type":57,"value":7168},"log",{"type":48,"tag":103,"props":7170,"children":7171},{"style":649},[7172],{"type":57,"value":716},{"type":48,"tag":103,"props":7174,"children":7175},{"style":643},[7176],{"type":57,"value":677},{"type":48,"tag":103,"props":7178,"children":7179},{"style":116},[7180],{"type":57,"value":7181},"disconnected",{"type":48,"tag":103,"props":7183,"children":7184},{"style":643},[7185],{"type":57,"value":677},{"type":48,"tag":103,"props":7187,"children":7188},{"style":649},[7189],{"type":57,"value":894},{"type":48,"tag":103,"props":7191,"children":7192},{"style":643},[7193],{"type":57,"value":2770},{"type":48,"tag":103,"props":7195,"children":7196},{"class":105,"line":1732},[7197,7201,7205],{"type":48,"tag":103,"props":7198,"children":7199},{"style":643},[7200],{"type":57,"value":2761},{"type":48,"tag":103,"props":7202,"children":7203},{"style":649},[7204],{"type":57,"value":1473},{"type":48,"tag":103,"props":7206,"children":7207},{"style":643},[7208],{"type":57,"value":2770},{"type":48,"tag":103,"props":7210,"children":7211},{"class":105,"line":1778},[7212,7216],{"type":48,"tag":103,"props":7213,"children":7214},{"style":649},[7215],{"type":57,"value":894},{"type":48,"tag":103,"props":7217,"children":7218},{"style":643},[7219],{"type":57,"value":682},{"type":48,"tag":103,"props":7221,"children":7222},{"class":105,"line":1794},[7223],{"type":48,"tag":103,"props":7224,"children":7225},{"emptyLinePlaceholder":689},[7226],{"type":57,"value":692},{"type":48,"tag":103,"props":7228,"children":7229},{"class":105,"line":1905},[7230,7234,7238,7243,7247],{"type":48,"tag":103,"props":7231,"children":7232},{"style":637},[7233],{"type":57,"value":701},{"type":48,"tag":103,"props":7235,"children":7236},{"style":637},[7237],{"type":57,"value":706},{"type":48,"tag":103,"props":7239,"children":7240},{"style":649},[7241],{"type":57,"value":7242}," handler",{"type":48,"tag":103,"props":7244,"children":7245},{"style":643},[7246],{"type":57,"value":2054},{"type":48,"tag":103,"props":7248,"children":7249},{"style":627},[7250],{"type":57,"value":7251}," \u002F\u002F Neon's { fetch, upgrade } contract\n",{"type":48,"tag":3676,"props":7253,"children":7254},{},[7255],{"type":48,"tag":49,"props":7256,"children":7257},{},[7258,7260,7266,7268,7274,7275,7281],{"type":57,"value":7259},"Don't put header-modifying middleware (e.g. CORS) on an ",{"type":48,"tag":62,"props":7261,"children":7263},{"className":7262},[],[7264],{"type":57,"value":7265},"upgradeWebSocket",{"type":57,"value":7267}," route — the helper rewrites headers internally and will throw. The ",{"type":48,"tag":82,"props":7269,"children":7271},{"href":7270},"#keeping-clients-in-sync-across-isolates-do-not-skip-this",[7272],{"type":57,"value":7273},"sync",{"type":57,"value":310},{"type":48,"tag":82,"props":7276,"children":7278},{"href":7277},"#client-must-reconnect",[7279],{"type":57,"value":7280},"reconnect",{"type":57,"value":7282}," guidance below applies unchanged.",{"type":48,"tag":7284,"props":7285,"children":7287},"h3",{"id":7286},"heartbeat-keep-the-socket-alive",[7288],{"type":57,"value":7289},"Heartbeat (keep the socket alive)",{"type":48,"tag":49,"props":7291,"children":7292},{},[7293,7295,7300,7302,7306,7308,7314],{"type":57,"value":7294},"A connection stays open ",{"type":48,"tag":53,"props":7296,"children":7297},{},[7298],{"type":57,"value":7299},"only while bytes flow",{"type":57,"value":7301},": Neon evicts a silent stream after 15 minutes (",{"type":48,"tag":82,"props":7303,"children":7304},{"href":305},[7305],{"type":57,"value":308},{"type":57,"value":7307},"), and intermediary proxies \u002F load balancers are usually far stricter (often tens of seconds). Don't rely on the app being chatty enough — send a periodic ping from the server so the socket never goes quiet. ",{"type":48,"tag":62,"props":7309,"children":7311},{"className":7310},[],[7312],{"type":57,"value":7313},"ws.ping()",{"type":57,"value":7315}," sends a WebSocket ping frame and the browser answers with a pong automatically, so there's no client code to write:",{"type":48,"tag":92,"props":7317,"children":7319},{"className":615,"code":7318,"language":617,"meta":97,"style":97},"const HEARTBEAT_MS = 25_000; \u002F\u002F comfortably under proxy idle timeouts\n\nconst beat = setInterval(() => {\n  for (const ws of clients) if (ws.readyState === ws.OPEN) ws.ping();\n}, HEARTBEAT_MS);\nbeat.unref?.();\n",[7320],{"type":48,"tag":62,"props":7321,"children":7322},{"__ignoreMap":97},[7323,7353,7360,7397,7494,7511],{"type":48,"tag":103,"props":7324,"children":7325},{"class":105,"line":106},[7326,7330,7335,7339,7344,7348],{"type":48,"tag":103,"props":7327,"children":7328},{"style":1188},[7329],{"type":57,"value":1191},{"type":48,"tag":103,"props":7331,"children":7332},{"style":649},[7333],{"type":57,"value":7334}," HEARTBEAT_MS ",{"type":48,"tag":103,"props":7336,"children":7337},{"style":643},[7338],{"type":57,"value":1201},{"type":48,"tag":103,"props":7340,"children":7341},{"style":1296},[7342],{"type":57,"value":7343}," 25_000",{"type":48,"tag":103,"props":7345,"children":7346},{"style":643},[7347],{"type":57,"value":2054},{"type":48,"tag":103,"props":7349,"children":7350},{"style":627},[7351],{"type":57,"value":7352}," \u002F\u002F comfortably under proxy idle timeouts\n",{"type":48,"tag":103,"props":7354,"children":7355},{"class":105,"line":633},[7356],{"type":48,"tag":103,"props":7357,"children":7358},{"emptyLinePlaceholder":689},[7359],{"type":57,"value":692},{"type":48,"tag":103,"props":7361,"children":7362},{"class":105,"line":685},[7363,7367,7372,7376,7381,7385,7389,7393],{"type":48,"tag":103,"props":7364,"children":7365},{"style":1188},[7366],{"type":57,"value":1191},{"type":48,"tag":103,"props":7368,"children":7369},{"style":649},[7370],{"type":57,"value":7371}," beat ",{"type":48,"tag":103,"props":7373,"children":7374},{"style":643},[7375],{"type":57,"value":1201},{"type":48,"tag":103,"props":7377,"children":7378},{"style":709},[7379],{"type":57,"value":7380}," setInterval",{"type":48,"tag":103,"props":7382,"children":7383},{"style":649},[7384],{"type":57,"value":716},{"type":48,"tag":103,"props":7386,"children":7387},{"style":643},[7388],{"type":57,"value":1376},{"type":48,"tag":103,"props":7390,"children":7391},{"style":1188},[7392],{"type":57,"value":1438},{"type":48,"tag":103,"props":7394,"children":7395},{"style":643},[7396],{"type":57,"value":740},{"type":48,"tag":103,"props":7398,"children":7399},{"class":105,"line":695},[7400,7405,7409,7413,7417,7422,7426,7430,7435,7439,7443,7447,7452,7456,7460,7464,7469,7473,7477,7481,7486,7490],{"type":48,"tag":103,"props":7401,"children":7402},{"style":637},[7403],{"type":57,"value":7404},"  for",{"type":48,"tag":103,"props":7406,"children":7407},{"style":728},[7408],{"type":57,"value":1423},{"type":48,"tag":103,"props":7410,"children":7411},{"style":1188},[7412],{"type":57,"value":1191},{"type":48,"tag":103,"props":7414,"children":7415},{"style":649},[7416],{"type":57,"value":6996},{"type":48,"tag":103,"props":7418,"children":7419},{"style":643},[7420],{"type":57,"value":7421}," of",{"type":48,"tag":103,"props":7423,"children":7424},{"style":649},[7425],{"type":57,"value":6205},{"type":48,"tag":103,"props":7427,"children":7428},{"style":728},[7429],{"type":57,"value":4354},{"type":48,"tag":103,"props":7431,"children":7432},{"style":637},[7433],{"type":57,"value":7434},"if",{"type":48,"tag":103,"props":7436,"children":7437},{"style":728},[7438],{"type":57,"value":1423},{"type":48,"tag":103,"props":7440,"children":7441},{"style":649},[7442],{"type":57,"value":5077},{"type":48,"tag":103,"props":7444,"children":7445},{"style":643},[7446],{"type":57,"value":158},{"type":48,"tag":103,"props":7448,"children":7449},{"style":649},[7450],{"type":57,"value":7451},"readyState",{"type":48,"tag":103,"props":7453,"children":7454},{"style":643},[7455],{"type":57,"value":4337},{"type":48,"tag":103,"props":7457,"children":7458},{"style":649},[7459],{"type":57,"value":6996},{"type":48,"tag":103,"props":7461,"children":7462},{"style":643},[7463],{"type":57,"value":158},{"type":48,"tag":103,"props":7465,"children":7466},{"style":649},[7467],{"type":57,"value":7468},"OPEN",{"type":48,"tag":103,"props":7470,"children":7471},{"style":728},[7472],{"type":57,"value":4354},{"type":48,"tag":103,"props":7474,"children":7475},{"style":649},[7476],{"type":57,"value":5077},{"type":48,"tag":103,"props":7478,"children":7479},{"style":643},[7480],{"type":57,"value":158},{"type":48,"tag":103,"props":7482,"children":7483},{"style":709},[7484],{"type":57,"value":7485},"ping",{"type":48,"tag":103,"props":7487,"children":7488},{"style":728},[7489],{"type":57,"value":1376},{"type":48,"tag":103,"props":7491,"children":7492},{"style":643},[7493],{"type":57,"value":682},{"type":48,"tag":103,"props":7495,"children":7496},{"class":105,"line":724},[7497,7502,7507],{"type":48,"tag":103,"props":7498,"children":7499},{"style":643},[7500],{"type":57,"value":7501},"},",{"type":48,"tag":103,"props":7503,"children":7504},{"style":649},[7505],{"type":57,"value":7506}," HEARTBEAT_MS)",{"type":48,"tag":103,"props":7508,"children":7509},{"style":643},[7510],{"type":57,"value":682},{"type":48,"tag":103,"props":7512,"children":7513},{"class":105,"line":743},[7514,7519,7523,7528,7532,7536],{"type":48,"tag":103,"props":7515,"children":7516},{"style":649},[7517],{"type":57,"value":7518},"beat",{"type":48,"tag":103,"props":7520,"children":7521},{"style":643},[7522],{"type":57,"value":158},{"type":48,"tag":103,"props":7524,"children":7525},{"style":709},[7526],{"type":57,"value":7527},"unref",{"type":48,"tag":103,"props":7529,"children":7530},{"style":643},[7531],{"type":57,"value":4532},{"type":48,"tag":103,"props":7533,"children":7534},{"style":649},[7535],{"type":57,"value":1376},{"type":48,"tag":103,"props":7537,"children":7538},{"style":643},[7539],{"type":57,"value":682},{"type":48,"tag":49,"props":7541,"children":7542},{},[7543,7545,7550,7552,7558],{"type":57,"value":7544},"(With the Hono ",{"type":48,"tag":62,"props":7546,"children":7548},{"className":7547},[],[7549],{"type":57,"value":7265},{"type":57,"value":7551}," helper you don't hold the raw socket, so send an application-level keepalive instead — e.g. ",{"type":48,"tag":62,"props":7553,"children":7555},{"className":7554},[],[7556],{"type":57,"value":7557},"ws.send(\"ping\")",{"type":57,"value":7559}," on the same interval, ignored by the client.)",{"type":48,"tag":7284,"props":7561,"children":7563},{"id":7562},"keeping-clients-in-sync-across-isolates-do-not-skip-this",[7564],{"type":57,"value":7565},"Keeping clients in sync across isolates (do not skip this)",{"type":48,"tag":49,"props":7567,"children":7568},{},[7569,7571,7576,7578,7584,7586,7591,7593,7598],{"type":57,"value":7570},"Under load the runtime runs ",{"type":48,"tag":53,"props":7572,"children":7573},{},[7574],{"type":57,"value":7575},"several isolates in parallel, each with its own copy of module state",{"type":57,"value":7577}," — so each isolate has its own ",{"type":48,"tag":62,"props":7579,"children":7581},{"className":7580},[],[7582],{"type":57,"value":7583},"clients",{"type":57,"value":7585}," set. Broadcasting only to that local set means a client on isolate A never sees an event produced on isolate B, and the feed silently fractures. It's easy to miss: ",{"type":48,"tag":62,"props":7587,"children":7589},{"className":7588},[],[7590],{"type":57,"value":190},{"type":57,"value":7592}," runs a single process (one isolate), so in-process broadcast always ",{"type":48,"tag":221,"props":7594,"children":7595},{},[7596],{"type":57,"value":7597},"looks",{"type":57,"value":7599}," fine locally but breaks in production, where concurrent connections spread across many isolates.",{"type":48,"tag":49,"props":7601,"children":7602},{},[7603,7605,7610,7612,7618,7620,7625,7627,7632,7634,7640],{"type":57,"value":7604},"Module state doesn't survive eviction anyway, so ",{"type":48,"tag":53,"props":7606,"children":7607},{},[7608],{"type":57,"value":7609},"Postgres is the shared source of truth",{"type":57,"value":7611},". Pick a fan-out strategy. In every snippet below, ",{"type":48,"tag":62,"props":7613,"children":7615},{"className":7614},[],[7616],{"type":57,"value":7617},"pool",{"type":57,"value":7619}," is a pooled ",{"type":48,"tag":62,"props":7621,"children":7623},{"className":7622},[],[7624],{"type":57,"value":243},{"type":57,"value":7626}," client and ",{"type":48,"tag":62,"props":7628,"children":7630},{"className":7629},[],[7631],{"type":57,"value":7583},{"type":57,"value":7633}," is this isolate's ",{"type":48,"tag":62,"props":7635,"children":7637},{"className":7636},[],[7638],{"type":57,"value":7639},"Set",{"type":57,"value":7641}," of live connections.",{"type":48,"tag":49,"props":7643,"children":7644},{},[7645,7650],{"type":48,"tag":53,"props":7646,"children":7647},{},[7648],{"type":57,"value":7649},"1. Poll Postgres — the default, and the only option that keeps Scale to Zero.",{"type":57,"value":7651}," Each isolate re-reads the shared state (or rows past a cursor) on a short interval and pushes changes to its own clients. One query per isolate per tick (not per client), and none when the isolate has no clients — so an idle compute still suspends.",{"type":48,"tag":92,"props":7653,"children":7655},{"className":615,"code":7654,"language":617,"meta":97,"style":97},"let lastId = 0;\nconst poller = setInterval(async () => {\n  if (clients.size === 0) return; \u002F\u002F no clients here → no query → compute can scale to zero\n  const { rows } = await pool.query(\n    \"SELECT id, payload FROM events WHERE id > $1 ORDER BY id\",\n    [lastId],\n  );\n  for (const { id, payload } of rows) {\n    lastId = id;\n    for (const ws of clients) if (ws.readyState === ws.OPEN) ws.send(payload);\n  }\n}, 1000);\npoller.unref?.();\n",[7656],{"type":48,"tag":62,"props":7657,"children":7658},{"__ignoreMap":97},[7659,7685,7726,7776,7821,7842,7863,7875,7927,7947,8048,8056,8076],{"type":48,"tag":103,"props":7660,"children":7661},{"class":105,"line":106},[7662,7667,7672,7676,7681],{"type":48,"tag":103,"props":7663,"children":7664},{"style":1188},[7665],{"type":57,"value":7666},"let",{"type":48,"tag":103,"props":7668,"children":7669},{"style":649},[7670],{"type":57,"value":7671}," lastId ",{"type":48,"tag":103,"props":7673,"children":7674},{"style":643},[7675],{"type":57,"value":1201},{"type":48,"tag":103,"props":7677,"children":7678},{"style":1296},[7679],{"type":57,"value":7680}," 0",{"type":48,"tag":103,"props":7682,"children":7683},{"style":643},[7684],{"type":57,"value":682},{"type":48,"tag":103,"props":7686,"children":7687},{"class":105,"line":633},[7688,7692,7697,7701,7705,7709,7714,7718,7722],{"type":48,"tag":103,"props":7689,"children":7690},{"style":1188},[7691],{"type":57,"value":1191},{"type":48,"tag":103,"props":7693,"children":7694},{"style":649},[7695],{"type":57,"value":7696}," poller ",{"type":48,"tag":103,"props":7698,"children":7699},{"style":643},[7700],{"type":57,"value":1201},{"type":48,"tag":103,"props":7702,"children":7703},{"style":709},[7704],{"type":57,"value":7380},{"type":48,"tag":103,"props":7706,"children":7707},{"style":649},[7708],{"type":57,"value":716},{"type":48,"tag":103,"props":7710,"children":7711},{"style":1188},[7712],{"type":57,"value":7713},"async",{"type":48,"tag":103,"props":7715,"children":7716},{"style":643},[7717],{"type":57,"value":5657},{"type":48,"tag":103,"props":7719,"children":7720},{"style":1188},[7721],{"type":57,"value":1438},{"type":48,"tag":103,"props":7723,"children":7724},{"style":643},[7725],{"type":57,"value":740},{"type":48,"tag":103,"props":7727,"children":7728},{"class":105,"line":685},[7729,7734,7738,7742,7746,7751,7755,7759,7763,7767,7771],{"type":48,"tag":103,"props":7730,"children":7731},{"style":637},[7732],{"type":57,"value":7733},"  if",{"type":48,"tag":103,"props":7735,"children":7736},{"style":728},[7737],{"type":57,"value":1423},{"type":48,"tag":103,"props":7739,"children":7740},{"style":649},[7741],{"type":57,"value":7583},{"type":48,"tag":103,"props":7743,"children":7744},{"style":643},[7745],{"type":57,"value":158},{"type":48,"tag":103,"props":7747,"children":7748},{"style":649},[7749],{"type":57,"value":7750},"size",{"type":48,"tag":103,"props":7752,"children":7753},{"style":643},[7754],{"type":57,"value":4337},{"type":48,"tag":103,"props":7756,"children":7757},{"style":1296},[7758],{"type":57,"value":7680},{"type":48,"tag":103,"props":7760,"children":7761},{"style":728},[7762],{"type":57,"value":4354},{"type":48,"tag":103,"props":7764,"children":7765},{"style":637},[7766],{"type":57,"value":4359},{"type":48,"tag":103,"props":7768,"children":7769},{"style":643},[7770],{"type":57,"value":2054},{"type":48,"tag":103,"props":7772,"children":7773},{"style":627},[7774],{"type":57,"value":7775}," \u002F\u002F no clients here → no query → compute can scale to zero\n",{"type":48,"tag":103,"props":7777,"children":7778},{"class":105,"line":695},[7779,7783,7787,7792,7796,7800,7804,7809,7813,7817],{"type":48,"tag":103,"props":7780,"children":7781},{"style":1188},[7782],{"type":57,"value":1549},{"type":48,"tag":103,"props":7784,"children":7785},{"style":643},[7786],{"type":57,"value":646},{"type":48,"tag":103,"props":7788,"children":7789},{"style":649},[7790],{"type":57,"value":7791}," rows",{"type":48,"tag":103,"props":7793,"children":7794},{"style":643},[7795],{"type":57,"value":657},{"type":48,"tag":103,"props":7797,"children":7798},{"style":643},[7799],{"type":57,"value":1567},{"type":48,"tag":103,"props":7801,"children":7802},{"style":637},[7803],{"type":57,"value":1572},{"type":48,"tag":103,"props":7805,"children":7806},{"style":649},[7807],{"type":57,"value":7808}," pool",{"type":48,"tag":103,"props":7810,"children":7811},{"style":643},[7812],{"type":57,"value":158},{"type":48,"tag":103,"props":7814,"children":7815},{"style":709},[7816],{"type":57,"value":6842},{"type":48,"tag":103,"props":7818,"children":7819},{"style":728},[7820],{"type":57,"value":6733},{"type":48,"tag":103,"props":7822,"children":7823},{"class":105,"line":724},[7824,7829,7834,7838],{"type":48,"tag":103,"props":7825,"children":7826},{"style":643},[7827],{"type":57,"value":7828},"    \"",{"type":48,"tag":103,"props":7830,"children":7831},{"style":116},[7832],{"type":57,"value":7833},"SELECT id, payload FROM events WHERE id > $1 ORDER BY id",{"type":48,"tag":103,"props":7835,"children":7836},{"style":643},[7837],{"type":57,"value":677},{"type":48,"tag":103,"props":7839,"children":7840},{"style":643},[7841],{"type":57,"value":2770},{"type":48,"tag":103,"props":7843,"children":7844},{"class":105,"line":743},[7845,7850,7855,7859],{"type":48,"tag":103,"props":7846,"children":7847},{"style":728},[7848],{"type":57,"value":7849},"    [",{"type":48,"tag":103,"props":7851,"children":7852},{"style":649},[7853],{"type":57,"value":7854},"lastId",{"type":48,"tag":103,"props":7856,"children":7857},{"style":728},[7858],{"type":57,"value":1648},{"type":48,"tag":103,"props":7860,"children":7861},{"style":643},[7862],{"type":57,"value":2770},{"type":48,"tag":103,"props":7864,"children":7865},{"class":105,"line":760},[7866,7871],{"type":48,"tag":103,"props":7867,"children":7868},{"style":728},[7869],{"type":57,"value":7870},"  )",{"type":48,"tag":103,"props":7872,"children":7873},{"style":643},[7874],{"type":57,"value":682},{"type":48,"tag":103,"props":7876,"children":7877},{"class":105,"line":777},[7878,7882,7886,7890,7894,7899,7903,7907,7911,7915,7919,7923],{"type":48,"tag":103,"props":7879,"children":7880},{"style":637},[7881],{"type":57,"value":7404},{"type":48,"tag":103,"props":7883,"children":7884},{"style":728},[7885],{"type":57,"value":1423},{"type":48,"tag":103,"props":7887,"children":7888},{"style":1188},[7889],{"type":57,"value":1191},{"type":48,"tag":103,"props":7891,"children":7892},{"style":643},[7893],{"type":57,"value":646},{"type":48,"tag":103,"props":7895,"children":7896},{"style":649},[7897],{"type":57,"value":7898}," id",{"type":48,"tag":103,"props":7900,"children":7901},{"style":643},[7902],{"type":57,"value":814},{"type":48,"tag":103,"props":7904,"children":7905},{"style":649},[7906],{"type":57,"value":4707},{"type":48,"tag":103,"props":7908,"children":7909},{"style":643},[7910],{"type":57,"value":657},{"type":48,"tag":103,"props":7912,"children":7913},{"style":643},[7914],{"type":57,"value":7421},{"type":48,"tag":103,"props":7916,"children":7917},{"style":649},[7918],{"type":57,"value":7791},{"type":48,"tag":103,"props":7920,"children":7921},{"style":728},[7922],{"type":57,"value":4354},{"type":48,"tag":103,"props":7924,"children":7925},{"style":643},[7926],{"type":57,"value":721},{"type":48,"tag":103,"props":7928,"children":7929},{"class":105,"line":786},[7930,7935,7939,7943],{"type":48,"tag":103,"props":7931,"children":7932},{"style":649},[7933],{"type":57,"value":7934},"    lastId",{"type":48,"tag":103,"props":7936,"children":7937},{"style":643},[7938],{"type":57,"value":1567},{"type":48,"tag":103,"props":7940,"children":7941},{"style":649},[7942],{"type":57,"value":7898},{"type":48,"tag":103,"props":7944,"children":7945},{"style":643},[7946],{"type":57,"value":682},{"type":48,"tag":103,"props":7948,"children":7949},{"class":105,"line":822},[7950,7955,7959,7963,7967,7971,7975,7979,7983,7987,7991,7995,7999,8003,8007,8011,8015,8019,8023,8027,8031,8035,8040,8044],{"type":48,"tag":103,"props":7951,"children":7952},{"style":637},[7953],{"type":57,"value":7954},"    for",{"type":48,"tag":103,"props":7956,"children":7957},{"style":728},[7958],{"type":57,"value":1423},{"type":48,"tag":103,"props":7960,"children":7961},{"style":1188},[7962],{"type":57,"value":1191},{"type":48,"tag":103,"props":7964,"children":7965},{"style":649},[7966],{"type":57,"value":6996},{"type":48,"tag":103,"props":7968,"children":7969},{"style":643},[7970],{"type":57,"value":7421},{"type":48,"tag":103,"props":7972,"children":7973},{"style":649},[7974],{"type":57,"value":6205},{"type":48,"tag":103,"props":7976,"children":7977},{"style":728},[7978],{"type":57,"value":4354},{"type":48,"tag":103,"props":7980,"children":7981},{"style":637},[7982],{"type":57,"value":7434},{"type":48,"tag":103,"props":7984,"children":7985},{"style":728},[7986],{"type":57,"value":1423},{"type":48,"tag":103,"props":7988,"children":7989},{"style":649},[7990],{"type":57,"value":5077},{"type":48,"tag":103,"props":7992,"children":7993},{"style":643},[7994],{"type":57,"value":158},{"type":48,"tag":103,"props":7996,"children":7997},{"style":649},[7998],{"type":57,"value":7451},{"type":48,"tag":103,"props":8000,"children":8001},{"style":643},[8002],{"type":57,"value":4337},{"type":48,"tag":103,"props":8004,"children":8005},{"style":649},[8006],{"type":57,"value":6996},{"type":48,"tag":103,"props":8008,"children":8009},{"style":643},[8010],{"type":57,"value":158},{"type":48,"tag":103,"props":8012,"children":8013},{"style":649},[8014],{"type":57,"value":7468},{"type":48,"tag":103,"props":8016,"children":8017},{"style":728},[8018],{"type":57,"value":4354},{"type":48,"tag":103,"props":8020,"children":8021},{"style":649},[8022],{"type":57,"value":5077},{"type":48,"tag":103,"props":8024,"children":8025},{"style":643},[8026],{"type":57,"value":158},{"type":48,"tag":103,"props":8028,"children":8029},{"style":709},[8030],{"type":57,"value":7017},{"type":48,"tag":103,"props":8032,"children":8033},{"style":728},[8034],{"type":57,"value":716},{"type":48,"tag":103,"props":8036,"children":8037},{"style":649},[8038],{"type":57,"value":8039},"payload",{"type":48,"tag":103,"props":8041,"children":8042},{"style":728},[8043],{"type":57,"value":894},{"type":48,"tag":103,"props":8045,"children":8046},{"style":643},[8047],{"type":57,"value":682},{"type":48,"tag":103,"props":8049,"children":8050},{"class":105,"line":857},[8051],{"type":48,"tag":103,"props":8052,"children":8053},{"style":643},[8054],{"type":57,"value":8055},"  }\n",{"type":48,"tag":103,"props":8057,"children":8058},{"class":105,"line":34},[8059,8063,8068,8072],{"type":48,"tag":103,"props":8060,"children":8061},{"style":643},[8062],{"type":57,"value":7501},{"type":48,"tag":103,"props":8064,"children":8065},{"style":1296},[8066],{"type":57,"value":8067}," 1000",{"type":48,"tag":103,"props":8069,"children":8070},{"style":649},[8071],{"type":57,"value":894},{"type":48,"tag":103,"props":8073,"children":8074},{"style":643},[8075],{"type":57,"value":682},{"type":48,"tag":103,"props":8077,"children":8078},{"class":105,"line":874},[8079,8084,8088,8092,8096,8100],{"type":48,"tag":103,"props":8080,"children":8081},{"style":649},[8082],{"type":57,"value":8083},"poller",{"type":48,"tag":103,"props":8085,"children":8086},{"style":643},[8087],{"type":57,"value":158},{"type":48,"tag":103,"props":8089,"children":8090},{"style":709},[8091],{"type":57,"value":7527},{"type":48,"tag":103,"props":8093,"children":8094},{"style":643},[8095],{"type":57,"value":4532},{"type":48,"tag":103,"props":8097,"children":8098},{"style":649},[8099],{"type":57,"value":1376},{"type":48,"tag":103,"props":8101,"children":8102},{"style":643},[8103],{"type":57,"value":682},{"type":48,"tag":206,"props":8105,"children":8106},{},[8107,8117,8142],{"type":48,"tag":210,"props":8108,"children":8109},{},[8110,8115],{"type":48,"tag":53,"props":8111,"children":8112},{},[8113],{"type":57,"value":8114},"Latency:",{"type":57,"value":8116}," up to the interval (~1s) — fine for counters, chat, and dashboards.",{"type":48,"tag":210,"props":8118,"children":8119},{},[8120,8125,8127,8133,8134,8140],{"type":48,"tag":53,"props":8121,"children":8122},{},[8123],{"type":57,"value":8124},"Scaling:",{"type":57,"value":8126}," database load grows with the number of live isolates, not clients. Keep the cursor on an indexed ",{"type":48,"tag":62,"props":8128,"children":8130},{"className":8129},[],[8131],{"type":57,"value":8132},"serial",{"type":57,"value":1410},{"type":48,"tag":62,"props":8135,"children":8137},{"className":8136},[],[8138],{"type":57,"value":8139},"bigserial",{"type":57,"value":8141}," PK and the interval sane.",{"type":48,"tag":210,"props":8143,"children":8144},{},[8145,8150],{"type":48,"tag":53,"props":8146,"children":8147},{},[8148],{"type":57,"value":8149},"Scale to Zero:",{"type":57,"value":8151}," ✅ preserved — polling stops when no clients are connected, so the compute suspends on its normal timer.",{"type":48,"tag":49,"props":8153,"children":8154},{},[8155,8173,8175,8180,8182,8187,8189,8194,8196,8201,8203,8210,8212,8217],{"type":48,"tag":53,"props":8156,"children":8157},{},[8158,8160,8165,8166,8171],{"type":57,"value":8159},"2. ",{"type":48,"tag":62,"props":8161,"children":8163},{"className":8162},[],[8164],{"type":57,"value":2901},{"type":57,"value":1410},{"type":48,"tag":62,"props":8167,"children":8169},{"className":8168},[],[8170],{"type":57,"value":2908},{"type":57,"value":8172}," — lowest latency, but requires disabling Scale to Zero.",{"type":57,"value":8174}," Each isolate ",{"type":48,"tag":62,"props":8176,"children":8178},{"className":8177},[],[8179],{"type":57,"value":2901},{"type":57,"value":8181},"s on a channel over a dedicated ",{"type":48,"tag":53,"props":8183,"children":8184},{},[8185],{"type":57,"value":8186},"unpooled",{"type":57,"value":8188}," connection; broadcasting is ",{"type":48,"tag":62,"props":8190,"children":8192},{"className":8191},[],[8193],{"type":57,"value":2908},{"type":57,"value":8195},", so every isolate (including the sender's) re-pushes to its sockets. Near-instant — but the listener holds an idle connection that ",{"type":48,"tag":53,"props":8197,"children":8198},{},[8199],{"type":57,"value":8200},"does not count as active",{"type":57,"value":8202},", so ",{"type":48,"tag":82,"props":8204,"children":8207},{"href":8205,"rel":8206},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fintroduction\u002Fscale-to-zero",[86],[8208],{"type":57,"value":8209},"Scale to Zero",{"type":57,"value":8211}," suspends the compute and drops it, silently killing the feed. Only use it on an ",{"type":48,"tag":53,"props":8213,"children":8214},{},[8215],{"type":57,"value":8216},"always-on",{"type":57,"value":8218}," compute (Scale to Zero disabled — a paid-plan setting).",{"type":48,"tag":92,"props":8220,"children":8222},{"className":615,"code":8221,"language":617,"meta":97,"style":97},"import { Pool, Client } from \"pg\";\n\nconst pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 5 });\nconst CHANNEL = \"chat_events\";\n\n\u002F\u002F One dedicated DIRECT connection per isolate, just to receive events.\n\u002F\u002F Use DATABASE_URL_UNPOOLED — LISTEN needs a real session, not a pooled one.\nconst listener = new Client({ connectionString: process.env.DATABASE_URL_UNPOOLED });\nlistener.connect().then(() => listener.query(`LISTEN ${CHANNEL}`));\nlistener.on(\"notification\", (msg) => {\n  if (!msg.payload) return;\n  for (const ws of clients) if (ws.readyState === ws.OPEN) ws.send(msg.payload);\n});\n\n\u002F\u002F Broadcast by NOTIFYing through the pool — every isolate's listener fires.\nfunction broadcast(event: unknown) {\n  return pool.query(\"SELECT pg_notify($1, $2)\", [CHANNEL, JSON.stringify(event)]);\n}\n",[8223],{"type":48,"tag":62,"props":8224,"children":8225},{"__ignoreMap":97},[8226,8274,8281,8368,8401,8408,8416,8424,8497,8586,8643,8682,8789,8804,8811,8819,8858,8941],{"type":48,"tag":103,"props":8227,"children":8228},{"class":105,"line":106},[8229,8233,8237,8241,8245,8250,8254,8258,8262,8266,8270],{"type":48,"tag":103,"props":8230,"children":8231},{"style":637},[8232],{"type":57,"value":640},{"type":48,"tag":103,"props":8234,"children":8235},{"style":643},[8236],{"type":57,"value":646},{"type":48,"tag":103,"props":8238,"children":8239},{"style":649},[8240],{"type":57,"value":1035},{"type":48,"tag":103,"props":8242,"children":8243},{"style":643},[8244],{"type":57,"value":814},{"type":48,"tag":103,"props":8246,"children":8247},{"style":649},[8248],{"type":57,"value":8249}," Client",{"type":48,"tag":103,"props":8251,"children":8252},{"style":643},[8253],{"type":57,"value":657},{"type":48,"tag":103,"props":8255,"children":8256},{"style":637},[8257],{"type":57,"value":662},{"type":48,"tag":103,"props":8259,"children":8260},{"style":643},[8261],{"type":57,"value":667},{"type":48,"tag":103,"props":8263,"children":8264},{"style":116},[8265],{"type":57,"value":243},{"type":48,"tag":103,"props":8267,"children":8268},{"style":643},[8269],{"type":57,"value":677},{"type":48,"tag":103,"props":8271,"children":8272},{"style":643},[8273],{"type":57,"value":682},{"type":48,"tag":103,"props":8275,"children":8276},{"class":105,"line":633},[8277],{"type":48,"tag":103,"props":8278,"children":8279},{"emptyLinePlaceholder":689},[8280],{"type":57,"value":692},{"type":48,"tag":103,"props":8282,"children":8283},{"class":105,"line":685},[8284,8288,8292,8296,8300,8304,8308,8312,8316,8320,8324,8328,8332,8336,8340,8344,8348,8352,8356,8360,8364],{"type":48,"tag":103,"props":8285,"children":8286},{"style":1188},[8287],{"type":57,"value":1191},{"type":48,"tag":103,"props":8289,"children":8290},{"style":649},[8291],{"type":57,"value":1226},{"type":48,"tag":103,"props":8293,"children":8294},{"style":643},[8295],{"type":57,"value":1201},{"type":48,"tag":103,"props":8297,"children":8298},{"style":643},[8299],{"type":57,"value":1235},{"type":48,"tag":103,"props":8301,"children":8302},{"style":709},[8303],{"type":57,"value":1035},{"type":48,"tag":103,"props":8305,"children":8306},{"style":649},[8307],{"type":57,"value":716},{"type":48,"tag":103,"props":8309,"children":8310},{"style":643},[8311],{"type":57,"value":1248},{"type":48,"tag":103,"props":8313,"children":8314},{"style":728},[8315],{"type":57,"value":1253},{"type":48,"tag":103,"props":8317,"children":8318},{"style":643},[8319],{"type":57,"value":612},{"type":48,"tag":103,"props":8321,"children":8322},{"style":649},[8323],{"type":57,"value":3193},{"type":48,"tag":103,"props":8325,"children":8326},{"style":643},[8327],{"type":57,"value":158},{"type":48,"tag":103,"props":8329,"children":8330},{"style":649},[8331],{"type":57,"value":2361},{"type":48,"tag":103,"props":8333,"children":8334},{"style":643},[8335],{"type":57,"value":158},{"type":48,"tag":103,"props":8337,"children":8338},{"style":649},[8339],{"type":57,"value":169},{"type":48,"tag":103,"props":8341,"children":8342},{"style":643},[8343],{"type":57,"value":814},{"type":48,"tag":103,"props":8345,"children":8346},{"style":728},[8347],{"type":57,"value":1289},{"type":48,"tag":103,"props":8349,"children":8350},{"style":643},[8351],{"type":57,"value":612},{"type":48,"tag":103,"props":8353,"children":8354},{"style":1296},[8355],{"type":57,"value":1299},{"type":48,"tag":103,"props":8357,"children":8358},{"style":643},[8359],{"type":57,"value":657},{"type":48,"tag":103,"props":8361,"children":8362},{"style":649},[8363],{"type":57,"value":894},{"type":48,"tag":103,"props":8365,"children":8366},{"style":643},[8367],{"type":57,"value":682},{"type":48,"tag":103,"props":8369,"children":8370},{"class":105,"line":695},[8371,8375,8380,8384,8388,8393,8397],{"type":48,"tag":103,"props":8372,"children":8373},{"style":1188},[8374],{"type":57,"value":1191},{"type":48,"tag":103,"props":8376,"children":8377},{"style":649},[8378],{"type":57,"value":8379}," CHANNEL ",{"type":48,"tag":103,"props":8381,"children":8382},{"style":643},[8383],{"type":57,"value":1201},{"type":48,"tag":103,"props":8385,"children":8386},{"style":643},[8387],{"type":57,"value":667},{"type":48,"tag":103,"props":8389,"children":8390},{"style":116},[8391],{"type":57,"value":8392},"chat_events",{"type":48,"tag":103,"props":8394,"children":8395},{"style":643},[8396],{"type":57,"value":677},{"type":48,"tag":103,"props":8398,"children":8399},{"style":643},[8400],{"type":57,"value":682},{"type":48,"tag":103,"props":8402,"children":8403},{"class":105,"line":724},[8404],{"type":48,"tag":103,"props":8405,"children":8406},{"emptyLinePlaceholder":689},[8407],{"type":57,"value":692},{"type":48,"tag":103,"props":8409,"children":8410},{"class":105,"line":743},[8411],{"type":48,"tag":103,"props":8412,"children":8413},{"style":627},[8414],{"type":57,"value":8415},"\u002F\u002F One dedicated DIRECT connection per isolate, just to receive events.\n",{"type":48,"tag":103,"props":8417,"children":8418},{"class":105,"line":760},[8419],{"type":48,"tag":103,"props":8420,"children":8421},{"style":627},[8422],{"type":57,"value":8423},"\u002F\u002F Use DATABASE_URL_UNPOOLED — LISTEN needs a real session, not a pooled one.\n",{"type":48,"tag":103,"props":8425,"children":8426},{"class":105,"line":777},[8427,8431,8436,8440,8444,8448,8452,8456,8460,8464,8468,8472,8476,8480,8485,8489,8493],{"type":48,"tag":103,"props":8428,"children":8429},{"style":1188},[8430],{"type":57,"value":1191},{"type":48,"tag":103,"props":8432,"children":8433},{"style":649},[8434],{"type":57,"value":8435}," listener ",{"type":48,"tag":103,"props":8437,"children":8438},{"style":643},[8439],{"type":57,"value":1201},{"type":48,"tag":103,"props":8441,"children":8442},{"style":643},[8443],{"type":57,"value":1235},{"type":48,"tag":103,"props":8445,"children":8446},{"style":709},[8447],{"type":57,"value":8249},{"type":48,"tag":103,"props":8449,"children":8450},{"style":649},[8451],{"type":57,"value":716},{"type":48,"tag":103,"props":8453,"children":8454},{"style":643},[8455],{"type":57,"value":1248},{"type":48,"tag":103,"props":8457,"children":8458},{"style":728},[8459],{"type":57,"value":1253},{"type":48,"tag":103,"props":8461,"children":8462},{"style":643},[8463],{"type":57,"value":612},{"type":48,"tag":103,"props":8465,"children":8466},{"style":649},[8467],{"type":57,"value":3193},{"type":48,"tag":103,"props":8469,"children":8470},{"style":643},[8471],{"type":57,"value":158},{"type":48,"tag":103,"props":8473,"children":8474},{"style":649},[8475],{"type":57,"value":2361},{"type":48,"tag":103,"props":8477,"children":8478},{"style":643},[8479],{"type":57,"value":158},{"type":48,"tag":103,"props":8481,"children":8482},{"style":649},[8483],{"type":57,"value":8484},"DATABASE_URL_UNPOOLED ",{"type":48,"tag":103,"props":8486,"children":8487},{"style":643},[8488],{"type":57,"value":889},{"type":48,"tag":103,"props":8490,"children":8491},{"style":649},[8492],{"type":57,"value":894},{"type":48,"tag":103,"props":8494,"children":8495},{"style":643},[8496],{"type":57,"value":682},{"type":48,"tag":103,"props":8498,"children":8499},{"class":105,"line":786},[8500,8505,8509,8514,8518,8522,8527,8531,8535,8539,8544,8548,8552,8556,8560,8565,8569,8574,8578,8582],{"type":48,"tag":103,"props":8501,"children":8502},{"style":649},[8503],{"type":57,"value":8504},"listener",{"type":48,"tag":103,"props":8506,"children":8507},{"style":643},[8508],{"type":57,"value":158},{"type":48,"tag":103,"props":8510,"children":8511},{"style":709},[8512],{"type":57,"value":8513},"connect",{"type":48,"tag":103,"props":8515,"children":8516},{"style":649},[8517],{"type":57,"value":1376},{"type":48,"tag":103,"props":8519,"children":8520},{"style":643},[8521],{"type":57,"value":158},{"type":48,"tag":103,"props":8523,"children":8524},{"style":709},[8525],{"type":57,"value":8526},"then",{"type":48,"tag":103,"props":8528,"children":8529},{"style":649},[8530],{"type":57,"value":716},{"type":48,"tag":103,"props":8532,"children":8533},{"style":643},[8534],{"type":57,"value":1376},{"type":48,"tag":103,"props":8536,"children":8537},{"style":1188},[8538],{"type":57,"value":1438},{"type":48,"tag":103,"props":8540,"children":8541},{"style":649},[8542],{"type":57,"value":8543}," listener",{"type":48,"tag":103,"props":8545,"children":8546},{"style":643},[8547],{"type":57,"value":158},{"type":48,"tag":103,"props":8549,"children":8550},{"style":709},[8551],{"type":57,"value":6842},{"type":48,"tag":103,"props":8553,"children":8554},{"style":649},[8555],{"type":57,"value":716},{"type":48,"tag":103,"props":8557,"children":8558},{"style":643},[8559],{"type":57,"value":4238},{"type":48,"tag":103,"props":8561,"children":8562},{"style":116},[8563],{"type":57,"value":8564},"LISTEN ",{"type":48,"tag":103,"props":8566,"children":8567},{"style":643},[8568],{"type":57,"value":7109},{"type":48,"tag":103,"props":8570,"children":8571},{"style":649},[8572],{"type":57,"value":8573},"CHANNEL",{"type":48,"tag":103,"props":8575,"children":8576},{"style":643},[8577],{"type":57,"value":7126},{"type":48,"tag":103,"props":8579,"children":8580},{"style":649},[8581],{"type":57,"value":1473},{"type":48,"tag":103,"props":8583,"children":8584},{"style":643},[8585],{"type":57,"value":682},{"type":48,"tag":103,"props":8587,"children":8588},{"class":105,"line":822},[8589,8593,8597,8601,8605,8609,8614,8618,8622,8626,8631,8635,8639],{"type":48,"tag":103,"props":8590,"children":8591},{"style":649},[8592],{"type":57,"value":8504},{"type":48,"tag":103,"props":8594,"children":8595},{"style":643},[8596],{"type":57,"value":158},{"type":48,"tag":103,"props":8598,"children":8599},{"style":709},[8600],{"type":57,"value":6171},{"type":48,"tag":103,"props":8602,"children":8603},{"style":649},[8604],{"type":57,"value":716},{"type":48,"tag":103,"props":8606,"children":8607},{"style":643},[8608],{"type":57,"value":677},{"type":48,"tag":103,"props":8610,"children":8611},{"style":116},[8612],{"type":57,"value":8613},"notification",{"type":48,"tag":103,"props":8615,"children":8616},{"style":643},[8617],{"type":57,"value":677},{"type":48,"tag":103,"props":8619,"children":8620},{"style":643},[8621],{"type":57,"value":814},{"type":48,"tag":103,"props":8623,"children":8624},{"style":643},[8625],{"type":57,"value":1423},{"type":48,"tag":103,"props":8627,"children":8628},{"style":1426},[8629],{"type":57,"value":8630},"msg",{"type":48,"tag":103,"props":8632,"children":8633},{"style":643},[8634],{"type":57,"value":894},{"type":48,"tag":103,"props":8636,"children":8637},{"style":1188},[8638],{"type":57,"value":1438},{"type":48,"tag":103,"props":8640,"children":8641},{"style":643},[8642],{"type":57,"value":740},{"type":48,"tag":103,"props":8644,"children":8645},{"class":105,"line":857},[8646,8650,8654,8658,8662,8666,8670,8674,8678],{"type":48,"tag":103,"props":8647,"children":8648},{"style":637},[8649],{"type":57,"value":7733},{"type":48,"tag":103,"props":8651,"children":8652},{"style":728},[8653],{"type":57,"value":1423},{"type":48,"tag":103,"props":8655,"children":8656},{"style":643},[8657],{"type":57,"value":3215},{"type":48,"tag":103,"props":8659,"children":8660},{"style":649},[8661],{"type":57,"value":8630},{"type":48,"tag":103,"props":8663,"children":8664},{"style":643},[8665],{"type":57,"value":158},{"type":48,"tag":103,"props":8667,"children":8668},{"style":649},[8669],{"type":57,"value":8039},{"type":48,"tag":103,"props":8671,"children":8672},{"style":728},[8673],{"type":57,"value":4354},{"type":48,"tag":103,"props":8675,"children":8676},{"style":637},[8677],{"type":57,"value":4359},{"type":48,"tag":103,"props":8679,"children":8680},{"style":643},[8681],{"type":57,"value":682},{"type":48,"tag":103,"props":8683,"children":8684},{"class":105,"line":34},[8685,8689,8693,8697,8701,8705,8709,8713,8717,8721,8725,8729,8733,8737,8741,8745,8749,8753,8757,8761,8765,8769,8773,8777,8781,8785],{"type":48,"tag":103,"props":8686,"children":8687},{"style":637},[8688],{"type":57,"value":7404},{"type":48,"tag":103,"props":8690,"children":8691},{"style":728},[8692],{"type":57,"value":1423},{"type":48,"tag":103,"props":8694,"children":8695},{"style":1188},[8696],{"type":57,"value":1191},{"type":48,"tag":103,"props":8698,"children":8699},{"style":649},[8700],{"type":57,"value":6996},{"type":48,"tag":103,"props":8702,"children":8703},{"style":643},[8704],{"type":57,"value":7421},{"type":48,"tag":103,"props":8706,"children":8707},{"style":649},[8708],{"type":57,"value":6205},{"type":48,"tag":103,"props":8710,"children":8711},{"style":728},[8712],{"type":57,"value":4354},{"type":48,"tag":103,"props":8714,"children":8715},{"style":637},[8716],{"type":57,"value":7434},{"type":48,"tag":103,"props":8718,"children":8719},{"style":728},[8720],{"type":57,"value":1423},{"type":48,"tag":103,"props":8722,"children":8723},{"style":649},[8724],{"type":57,"value":5077},{"type":48,"tag":103,"props":8726,"children":8727},{"style":643},[8728],{"type":57,"value":158},{"type":48,"tag":103,"props":8730,"children":8731},{"style":649},[8732],{"type":57,"value":7451},{"type":48,"tag":103,"props":8734,"children":8735},{"style":643},[8736],{"type":57,"value":4337},{"type":48,"tag":103,"props":8738,"children":8739},{"style":649},[8740],{"type":57,"value":6996},{"type":48,"tag":103,"props":8742,"children":8743},{"style":643},[8744],{"type":57,"value":158},{"type":48,"tag":103,"props":8746,"children":8747},{"style":649},[8748],{"type":57,"value":7468},{"type":48,"tag":103,"props":8750,"children":8751},{"style":728},[8752],{"type":57,"value":4354},{"type":48,"tag":103,"props":8754,"children":8755},{"style":649},[8756],{"type":57,"value":5077},{"type":48,"tag":103,"props":8758,"children":8759},{"style":643},[8760],{"type":57,"value":158},{"type":48,"tag":103,"props":8762,"children":8763},{"style":709},[8764],{"type":57,"value":7017},{"type":48,"tag":103,"props":8766,"children":8767},{"style":728},[8768],{"type":57,"value":716},{"type":48,"tag":103,"props":8770,"children":8771},{"style":649},[8772],{"type":57,"value":8630},{"type":48,"tag":103,"props":8774,"children":8775},{"style":643},[8776],{"type":57,"value":158},{"type":48,"tag":103,"props":8778,"children":8779},{"style":649},[8780],{"type":57,"value":8039},{"type":48,"tag":103,"props":8782,"children":8783},{"style":728},[8784],{"type":57,"value":894},{"type":48,"tag":103,"props":8786,"children":8787},{"style":643},[8788],{"type":57,"value":682},{"type":48,"tag":103,"props":8790,"children":8791},{"class":105,"line":874},[8792,8796,8800],{"type":48,"tag":103,"props":8793,"children":8794},{"style":643},[8795],{"type":57,"value":889},{"type":48,"tag":103,"props":8797,"children":8798},{"style":649},[8799],{"type":57,"value":894},{"type":48,"tag":103,"props":8801,"children":8802},{"style":643},[8803],{"type":57,"value":682},{"type":48,"tag":103,"props":8805,"children":8806},{"class":105,"line":883},[8807],{"type":48,"tag":103,"props":8808,"children":8809},{"emptyLinePlaceholder":689},[8810],{"type":57,"value":692},{"type":48,"tag":103,"props":8812,"children":8813},{"class":105,"line":1480},[8814],{"type":48,"tag":103,"props":8815,"children":8816},{"style":627},[8817],{"type":57,"value":8818},"\u002F\u002F Broadcast by NOTIFYing through the pool — every isolate's listener fires.\n",{"type":48,"tag":103,"props":8820,"children":8821},{"class":105,"line":1543},[8822,8827,8832,8836,8841,8845,8850,8854],{"type":48,"tag":103,"props":8823,"children":8824},{"style":1188},[8825],{"type":57,"value":8826},"function",{"type":48,"tag":103,"props":8828,"children":8829},{"style":709},[8830],{"type":57,"value":8831}," broadcast",{"type":48,"tag":103,"props":8833,"children":8834},{"style":643},[8835],{"type":57,"value":716},{"type":48,"tag":103,"props":8837,"children":8838},{"style":1426},[8839],{"type":57,"value":8840},"event",{"type":48,"tag":103,"props":8842,"children":8843},{"style":643},[8844],{"type":57,"value":612},{"type":48,"tag":103,"props":8846,"children":8847},{"style":110},[8848],{"type":57,"value":8849}," unknown",{"type":48,"tag":103,"props":8851,"children":8852},{"style":643},[8853],{"type":57,"value":894},{"type":48,"tag":103,"props":8855,"children":8856},{"style":643},[8857],{"type":57,"value":740},{"type":48,"tag":103,"props":8859,"children":8860},{"class":105,"line":1628},[8861,8865,8869,8873,8877,8881,8885,8890,8894,8898,8902,8906,8910,8915,8919,8924,8928,8932,8937],{"type":48,"tag":103,"props":8862,"children":8863},{"style":637},[8864],{"type":57,"value":1738},{"type":48,"tag":103,"props":8866,"children":8867},{"style":649},[8868],{"type":57,"value":7808},{"type":48,"tag":103,"props":8870,"children":8871},{"style":643},[8872],{"type":57,"value":158},{"type":48,"tag":103,"props":8874,"children":8875},{"style":709},[8876],{"type":57,"value":6842},{"type":48,"tag":103,"props":8878,"children":8879},{"style":728},[8880],{"type":57,"value":716},{"type":48,"tag":103,"props":8882,"children":8883},{"style":643},[8884],{"type":57,"value":677},{"type":48,"tag":103,"props":8886,"children":8887},{"style":116},[8888],{"type":57,"value":8889},"SELECT pg_notify($1, $2)",{"type":48,"tag":103,"props":8891,"children":8892},{"style":643},[8893],{"type":57,"value":677},{"type":48,"tag":103,"props":8895,"children":8896},{"style":643},[8897],{"type":57,"value":814},{"type":48,"tag":103,"props":8899,"children":8900},{"style":728},[8901],{"type":57,"value":1638},{"type":48,"tag":103,"props":8903,"children":8904},{"style":649},[8905],{"type":57,"value":8573},{"type":48,"tag":103,"props":8907,"children":8908},{"style":643},[8909],{"type":57,"value":814},{"type":48,"tag":103,"props":8911,"children":8912},{"style":649},[8913],{"type":57,"value":8914}," JSON",{"type":48,"tag":103,"props":8916,"children":8917},{"style":643},[8918],{"type":57,"value":158},{"type":48,"tag":103,"props":8920,"children":8921},{"style":709},[8922],{"type":57,"value":8923},"stringify",{"type":48,"tag":103,"props":8925,"children":8926},{"style":728},[8927],{"type":57,"value":716},{"type":48,"tag":103,"props":8929,"children":8930},{"style":649},[8931],{"type":57,"value":8840},{"type":48,"tag":103,"props":8933,"children":8934},{"style":728},[8935],{"type":57,"value":8936},")])",{"type":48,"tag":103,"props":8938,"children":8939},{"style":643},[8940],{"type":57,"value":682},{"type":48,"tag":103,"props":8942,"children":8943},{"class":105,"line":1732},[8944],{"type":48,"tag":103,"props":8945,"children":8946},{"style":643},[8947],{"type":57,"value":3234},{"type":48,"tag":49,"props":8949,"children":8950},{},[8951,8965],{"type":48,"tag":53,"props":8952,"children":8953},{},[8954,8956,8963],{"type":57,"value":8955},"3. External pub\u002Fsub (e.g. ",{"type":48,"tag":82,"props":8957,"children":8960},{"href":8958,"rel":8959},"https:\u002F\u002Fupstash.com",[86],[8961],{"type":57,"value":8962},"Upstash",{"type":57,"value":8964}," Redis) — best at scale.",{"type":57,"value":8966}," For high fan-out, sub-second latency at large connection counts, or multi-region, publish\u002Fsubscribe through a dedicated broker. Highest throughput, and it doesn't touch Postgres or block Scale to Zero — at the cost of another service to run.",{"type":48,"tag":49,"props":8968,"children":8969},{},[8970,8975,8977,8982,8984,8989,8990,8995],{"type":48,"tag":53,"props":8971,"children":8972},{},[8973],{"type":57,"value":8974},"Rule of thumb:",{"type":57,"value":8976}," start with ",{"type":48,"tag":53,"props":8978,"children":8979},{},[8980],{"type":57,"value":8981},"polling",{"type":57,"value":8983}," (works with Scale to Zero, no extra infra); switch to ",{"type":48,"tag":62,"props":8985,"children":8987},{"className":8986},[],[8988],{"type":57,"value":2901},{"type":57,"value":1410},{"type":48,"tag":62,"props":8991,"children":8993},{"className":8992},[],[8994],{"type":57,"value":2908},{"type":57,"value":8996}," only on always-on compute that needs sub-second latency; move to Redis when fan-out outgrows Postgres.",{"type":48,"tag":7284,"props":8998,"children":9000},{"id":8999},"client-must-reconnect",[9001],{"type":57,"value":9002},"Client must reconnect",{"type":48,"tag":49,"props":9004,"children":9005},{},[9006,9008,9013,9015,9020,9022,9027],{"type":57,"value":9007},"Idle functions are evicted (and isolates restart for operational reasons), so a client's socket ",{"type":48,"tag":53,"props":9009,"children":9010},{},[9011],{"type":57,"value":9012},"will",{"type":57,"value":9014}," drop — treat reconnection as normal, not exceptional. Reconnect with exponential backoff, capped, and ",{"type":48,"tag":53,"props":9016,"children":9017},{},[9018],{"type":57,"value":9019},"re-mint a fresh token on every attempt",{"type":57,"value":9021}," (tokens are short-lived, so a stale one fails the ",{"type":48,"tag":62,"props":9023,"children":9025},{"className":9024},[],[9026],{"type":57,"value":5109},{"type":57,"value":9028}," auth check):",{"type":48,"tag":92,"props":9030,"children":9032},{"className":615,"code":9031,"language":617,"meta":97,"style":97},"let closed = false, retry = 0, timer: ReturnType\u003Ctypeof setTimeout>;\n\nasync function connect() {\n  if (closed) return;\n  const token = await getToken(); \u002F\u002F re-mint each attempt; short-lived\n  const ws = new WebSocket(`${WS_URL}?token=${encodeURIComponent(token)}`);\n  ws.onopen = () => { retry = 0; };          \u002F\u002F reset backoff on success\n  ws.onmessage = (e) => { \u002F* apply the event *\u002F };\n  ws.onclose = () => {\n    if (!closed) timer = setTimeout(connect, Math.min(1000 * 2 ** retry++, 15000));\n  };\n  ws.onerror = () => ws.close();             \u002F\u002F let onclose drive the retry\n}\nconnect();\n",[9033],{"type":48,"tag":62,"props":9034,"children":9035},{"__ignoreMap":97},[9036,9107,9114,9139,9167,9205,9275,9335,9386,9418,9526,9534,9587,9594],{"type":48,"tag":103,"props":9037,"children":9038},{"class":105,"line":106},[9039,9043,9048,9052,9057,9061,9066,9070,9074,9078,9083,9087,9092,9097,9102],{"type":48,"tag":103,"props":9040,"children":9041},{"style":1188},[9042],{"type":57,"value":7666},{"type":48,"tag":103,"props":9044,"children":9045},{"style":649},[9046],{"type":57,"value":9047}," closed ",{"type":48,"tag":103,"props":9049,"children":9050},{"style":643},[9051],{"type":57,"value":1201},{"type":48,"tag":103,"props":9053,"children":9054},{"style":5596},[9055],{"type":57,"value":9056}," false",{"type":48,"tag":103,"props":9058,"children":9059},{"style":643},[9060],{"type":57,"value":814},{"type":48,"tag":103,"props":9062,"children":9063},{"style":649},[9064],{"type":57,"value":9065}," retry ",{"type":48,"tag":103,"props":9067,"children":9068},{"style":643},[9069],{"type":57,"value":1201},{"type":48,"tag":103,"props":9071,"children":9072},{"style":1296},[9073],{"type":57,"value":7680},{"type":48,"tag":103,"props":9075,"children":9076},{"style":643},[9077],{"type":57,"value":814},{"type":48,"tag":103,"props":9079,"children":9080},{"style":649},[9081],{"type":57,"value":9082}," timer",{"type":48,"tag":103,"props":9084,"children":9085},{"style":643},[9086],{"type":57,"value":612},{"type":48,"tag":103,"props":9088,"children":9089},{"style":110},[9090],{"type":57,"value":9091}," ReturnType",{"type":48,"tag":103,"props":9093,"children":9094},{"style":643},[9095],{"type":57,"value":9096},"\u003Ctypeof",{"type":48,"tag":103,"props":9098,"children":9099},{"style":649},[9100],{"type":57,"value":9101}," setTimeout",{"type":48,"tag":103,"props":9103,"children":9104},{"style":643},[9105],{"type":57,"value":9106},">;\n",{"type":48,"tag":103,"props":9108,"children":9109},{"class":105,"line":633},[9110],{"type":48,"tag":103,"props":9111,"children":9112},{"emptyLinePlaceholder":689},[9113],{"type":57,"value":692},{"type":48,"tag":103,"props":9115,"children":9116},{"class":105,"line":685},[9117,9121,9126,9131,9135],{"type":48,"tag":103,"props":9118,"children":9119},{"style":1188},[9120],{"type":57,"value":7713},{"type":48,"tag":103,"props":9122,"children":9123},{"style":1188},[9124],{"type":57,"value":9125}," function",{"type":48,"tag":103,"props":9127,"children":9128},{"style":709},[9129],{"type":57,"value":9130}," connect",{"type":48,"tag":103,"props":9132,"children":9133},{"style":643},[9134],{"type":57,"value":1376},{"type":48,"tag":103,"props":9136,"children":9137},{"style":643},[9138],{"type":57,"value":740},{"type":48,"tag":103,"props":9140,"children":9141},{"class":105,"line":695},[9142,9146,9150,9155,9159,9163],{"type":48,"tag":103,"props":9143,"children":9144},{"style":637},[9145],{"type":57,"value":7733},{"type":48,"tag":103,"props":9147,"children":9148},{"style":728},[9149],{"type":57,"value":1423},{"type":48,"tag":103,"props":9151,"children":9152},{"style":649},[9153],{"type":57,"value":9154},"closed",{"type":48,"tag":103,"props":9156,"children":9157},{"style":728},[9158],{"type":57,"value":4354},{"type":48,"tag":103,"props":9160,"children":9161},{"style":637},[9162],{"type":57,"value":4359},{"type":48,"tag":103,"props":9164,"children":9165},{"style":643},[9166],{"type":57,"value":682},{"type":48,"tag":103,"props":9168,"children":9169},{"class":105,"line":724},[9170,9174,9179,9183,9187,9192,9196,9200],{"type":48,"tag":103,"props":9171,"children":9172},{"style":1188},[9173],{"type":57,"value":1549},{"type":48,"tag":103,"props":9175,"children":9176},{"style":649},[9177],{"type":57,"value":9178}," token",{"type":48,"tag":103,"props":9180,"children":9181},{"style":643},[9182],{"type":57,"value":1567},{"type":48,"tag":103,"props":9184,"children":9185},{"style":637},[9186],{"type":57,"value":1572},{"type":48,"tag":103,"props":9188,"children":9189},{"style":709},[9190],{"type":57,"value":9191}," getToken",{"type":48,"tag":103,"props":9193,"children":9194},{"style":728},[9195],{"type":57,"value":1376},{"type":48,"tag":103,"props":9197,"children":9198},{"style":643},[9199],{"type":57,"value":2054},{"type":48,"tag":103,"props":9201,"children":9202},{"style":627},[9203],{"type":57,"value":9204}," \u002F\u002F re-mint each attempt; short-lived\n",{"type":48,"tag":103,"props":9206,"children":9207},{"class":105,"line":743},[9208,9212,9216,9220,9224,9228,9232,9236,9241,9245,9249,9253,9258,9263,9267,9271],{"type":48,"tag":103,"props":9209,"children":9210},{"style":1188},[9211],{"type":57,"value":1549},{"type":48,"tag":103,"props":9213,"children":9214},{"style":649},[9215],{"type":57,"value":6996},{"type":48,"tag":103,"props":9217,"children":9218},{"style":643},[9219],{"type":57,"value":1567},{"type":48,"tag":103,"props":9221,"children":9222},{"style":643},[9223],{"type":57,"value":1235},{"type":48,"tag":103,"props":9225,"children":9226},{"style":709},[9227],{"type":57,"value":5475},{"type":48,"tag":103,"props":9229,"children":9230},{"style":728},[9231],{"type":57,"value":716},{"type":48,"tag":103,"props":9233,"children":9234},{"style":643},[9235],{"type":57,"value":4202},{"type":48,"tag":103,"props":9237,"children":9238},{"style":649},[9239],{"type":57,"value":9240},"WS_URL",{"type":48,"tag":103,"props":9242,"children":9243},{"style":643},[9244],{"type":57,"value":889},{"type":48,"tag":103,"props":9246,"children":9247},{"style":116},[9248],{"type":57,"value":5327},{"type":48,"tag":103,"props":9250,"children":9251},{"style":643},[9252],{"type":57,"value":7109},{"type":48,"tag":103,"props":9254,"children":9255},{"style":709},[9256],{"type":57,"value":9257},"encodeURIComponent",{"type":48,"tag":103,"props":9259,"children":9260},{"style":649},[9261],{"type":57,"value":9262},"(token)",{"type":48,"tag":103,"props":9264,"children":9265},{"style":643},[9266],{"type":57,"value":7126},{"type":48,"tag":103,"props":9268,"children":9269},{"style":728},[9270],{"type":57,"value":894},{"type":48,"tag":103,"props":9272,"children":9273},{"style":643},[9274],{"type":57,"value":682},{"type":48,"tag":103,"props":9276,"children":9277},{"class":105,"line":760},[9278,9283,9287,9292,9296,9300,9304,9308,9313,9317,9321,9325,9330],{"type":48,"tag":103,"props":9279,"children":9280},{"style":649},[9281],{"type":57,"value":9282},"  ws",{"type":48,"tag":103,"props":9284,"children":9285},{"style":643},[9286],{"type":57,"value":158},{"type":48,"tag":103,"props":9288,"children":9289},{"style":709},[9290],{"type":57,"value":9291},"onopen",{"type":48,"tag":103,"props":9293,"children":9294},{"style":643},[9295],{"type":57,"value":1567},{"type":48,"tag":103,"props":9297,"children":9298},{"style":643},[9299],{"type":57,"value":5657},{"type":48,"tag":103,"props":9301,"children":9302},{"style":1188},[9303],{"type":57,"value":1438},{"type":48,"tag":103,"props":9305,"children":9306},{"style":643},[9307],{"type":57,"value":646},{"type":48,"tag":103,"props":9309,"children":9310},{"style":649},[9311],{"type":57,"value":9312}," retry",{"type":48,"tag":103,"props":9314,"children":9315},{"style":643},[9316],{"type":57,"value":1567},{"type":48,"tag":103,"props":9318,"children":9319},{"style":1296},[9320],{"type":57,"value":7680},{"type":48,"tag":103,"props":9322,"children":9323},{"style":643},[9324],{"type":57,"value":2054},{"type":48,"tag":103,"props":9326,"children":9327},{"style":643},[9328],{"type":57,"value":9329}," };",{"type":48,"tag":103,"props":9331,"children":9332},{"style":627},[9333],{"type":57,"value":9334},"          \u002F\u002F reset backoff on success\n",{"type":48,"tag":103,"props":9336,"children":9337},{"class":105,"line":777},[9338,9342,9346,9351,9355,9359,9364,9368,9372,9376,9381],{"type":48,"tag":103,"props":9339,"children":9340},{"style":649},[9341],{"type":57,"value":9282},{"type":48,"tag":103,"props":9343,"children":9344},{"style":643},[9345],{"type":57,"value":158},{"type":48,"tag":103,"props":9347,"children":9348},{"style":709},[9349],{"type":57,"value":9350},"onmessage",{"type":48,"tag":103,"props":9352,"children":9353},{"style":643},[9354],{"type":57,"value":1567},{"type":48,"tag":103,"props":9356,"children":9357},{"style":643},[9358],{"type":57,"value":1423},{"type":48,"tag":103,"props":9360,"children":9361},{"style":1426},[9362],{"type":57,"value":9363},"e",{"type":48,"tag":103,"props":9365,"children":9366},{"style":643},[9367],{"type":57,"value":894},{"type":48,"tag":103,"props":9369,"children":9370},{"style":1188},[9371],{"type":57,"value":1438},{"type":48,"tag":103,"props":9373,"children":9374},{"style":643},[9375],{"type":57,"value":646},{"type":48,"tag":103,"props":9377,"children":9378},{"style":627},[9379],{"type":57,"value":9380}," \u002F* apply the event *\u002F",{"type":48,"tag":103,"props":9382,"children":9383},{"style":643},[9384],{"type":57,"value":9385}," };\n",{"type":48,"tag":103,"props":9387,"children":9388},{"class":105,"line":786},[9389,9393,9397,9402,9406,9410,9414],{"type":48,"tag":103,"props":9390,"children":9391},{"style":649},[9392],{"type":57,"value":9282},{"type":48,"tag":103,"props":9394,"children":9395},{"style":643},[9396],{"type":57,"value":158},{"type":48,"tag":103,"props":9398,"children":9399},{"style":709},[9400],{"type":57,"value":9401},"onclose",{"type":48,"tag":103,"props":9403,"children":9404},{"style":643},[9405],{"type":57,"value":1567},{"type":48,"tag":103,"props":9407,"children":9408},{"style":643},[9409],{"type":57,"value":5657},{"type":48,"tag":103,"props":9411,"children":9412},{"style":1188},[9413],{"type":57,"value":1438},{"type":48,"tag":103,"props":9415,"children":9416},{"style":643},[9417],{"type":57,"value":740},{"type":48,"tag":103,"props":9419,"children":9420},{"class":105,"line":822},[9421,9425,9429,9433,9437,9441,9446,9450,9454,9458,9462,9466,9471,9475,9480,9484,9489,9494,9499,9504,9508,9513,9518,9522],{"type":48,"tag":103,"props":9422,"children":9423},{"style":637},[9424],{"type":57,"value":4315},{"type":48,"tag":103,"props":9426,"children":9427},{"style":728},[9428],{"type":57,"value":1423},{"type":48,"tag":103,"props":9430,"children":9431},{"style":643},[9432],{"type":57,"value":3215},{"type":48,"tag":103,"props":9434,"children":9435},{"style":649},[9436],{"type":57,"value":9154},{"type":48,"tag":103,"props":9438,"children":9439},{"style":728},[9440],{"type":57,"value":4354},{"type":48,"tag":103,"props":9442,"children":9443},{"style":649},[9444],{"type":57,"value":9445},"timer",{"type":48,"tag":103,"props":9447,"children":9448},{"style":643},[9449],{"type":57,"value":1567},{"type":48,"tag":103,"props":9451,"children":9452},{"style":709},[9453],{"type":57,"value":9101},{"type":48,"tag":103,"props":9455,"children":9456},{"style":728},[9457],{"type":57,"value":716},{"type":48,"tag":103,"props":9459,"children":9460},{"style":649},[9461],{"type":57,"value":8513},{"type":48,"tag":103,"props":9463,"children":9464},{"style":643},[9465],{"type":57,"value":814},{"type":48,"tag":103,"props":9467,"children":9468},{"style":649},[9469],{"type":57,"value":9470}," Math",{"type":48,"tag":103,"props":9472,"children":9473},{"style":643},[9474],{"type":57,"value":158},{"type":48,"tag":103,"props":9476,"children":9477},{"style":709},[9478],{"type":57,"value":9479},"min",{"type":48,"tag":103,"props":9481,"children":9482},{"style":728},[9483],{"type":57,"value":716},{"type":48,"tag":103,"props":9485,"children":9486},{"style":1296},[9487],{"type":57,"value":9488},"1000",{"type":48,"tag":103,"props":9490,"children":9491},{"style":643},[9492],{"type":57,"value":9493}," *",{"type":48,"tag":103,"props":9495,"children":9496},{"style":1296},[9497],{"type":57,"value":9498}," 2",{"type":48,"tag":103,"props":9500,"children":9501},{"style":643},[9502],{"type":57,"value":9503}," **",{"type":48,"tag":103,"props":9505,"children":9506},{"style":649},[9507],{"type":57,"value":9312},{"type":48,"tag":103,"props":9509,"children":9510},{"style":643},[9511],{"type":57,"value":9512},"++,",{"type":48,"tag":103,"props":9514,"children":9515},{"style":1296},[9516],{"type":57,"value":9517}," 15000",{"type":48,"tag":103,"props":9519,"children":9520},{"style":728},[9521],{"type":57,"value":1473},{"type":48,"tag":103,"props":9523,"children":9524},{"style":643},[9525],{"type":57,"value":682},{"type":48,"tag":103,"props":9527,"children":9528},{"class":105,"line":857},[9529],{"type":48,"tag":103,"props":9530,"children":9531},{"style":643},[9532],{"type":57,"value":9533},"  };\n",{"type":48,"tag":103,"props":9535,"children":9536},{"class":105,"line":34},[9537,9541,9545,9550,9554,9558,9562,9566,9570,9574,9578,9582],{"type":48,"tag":103,"props":9538,"children":9539},{"style":649},[9540],{"type":57,"value":9282},{"type":48,"tag":103,"props":9542,"children":9543},{"style":643},[9544],{"type":57,"value":158},{"type":48,"tag":103,"props":9546,"children":9547},{"style":709},[9548],{"type":57,"value":9549},"onerror",{"type":48,"tag":103,"props":9551,"children":9552},{"style":643},[9553],{"type":57,"value":1567},{"type":48,"tag":103,"props":9555,"children":9556},{"style":643},[9557],{"type":57,"value":5657},{"type":48,"tag":103,"props":9559,"children":9560},{"style":1188},[9561],{"type":57,"value":1438},{"type":48,"tag":103,"props":9563,"children":9564},{"style":649},[9565],{"type":57,"value":6996},{"type":48,"tag":103,"props":9567,"children":9568},{"style":643},[9569],{"type":57,"value":158},{"type":48,"tag":103,"props":9571,"children":9572},{"style":709},[9573],{"type":57,"value":6184},{"type":48,"tag":103,"props":9575,"children":9576},{"style":728},[9577],{"type":57,"value":1376},{"type":48,"tag":103,"props":9579,"children":9580},{"style":643},[9581],{"type":57,"value":2054},{"type":48,"tag":103,"props":9583,"children":9584},{"style":627},[9585],{"type":57,"value":9586},"             \u002F\u002F let onclose drive the retry\n",{"type":48,"tag":103,"props":9588,"children":9589},{"class":105,"line":874},[9590],{"type":48,"tag":103,"props":9591,"children":9592},{"style":643},[9593],{"type":57,"value":3234},{"type":48,"tag":103,"props":9595,"children":9596},{"class":105,"line":883},[9597,9601,9605],{"type":48,"tag":103,"props":9598,"children":9599},{"style":709},[9600],{"type":57,"value":8513},{"type":48,"tag":103,"props":9602,"children":9603},{"style":649},[9604],{"type":57,"value":1376},{"type":48,"tag":103,"props":9606,"children":9607},{"style":643},[9608],{"type":57,"value":682},{"type":48,"tag":49,"props":9610,"children":9611},{},[9612,9614,9619,9621,9626,9627,9632,9634,9639],{"type":57,"value":9613},"Together — Hono ",{"type":48,"tag":62,"props":9615,"children":9617},{"className":9616},[],[9618],{"type":57,"value":4016},{"type":57,"value":9620}," + ",{"type":48,"tag":62,"props":9622,"children":9624},{"className":9623},[],[9625],{"type":57,"value":5077},{"type":57,"value":2280},{"type":48,"tag":62,"props":9628,"children":9630},{"className":9629},[],[9631],{"type":57,"value":5109},{"type":57,"value":9633},", JWT auth over ",{"type":48,"tag":62,"props":9635,"children":9637},{"className":9636},[],[9638],{"type":57,"value":5327},{"type":57,"value":9640},", cross-isolate fan-out, and client backoff — these compose into a complete realtime chat backend on a single function.",{"type":48,"tag":194,"props":9642,"children":9644},{"id":9643},"server-sent-events-sse",[9645],{"type":57,"value":351},{"type":48,"tag":49,"props":9647,"children":9648},{},[9649,9651,9656,9658,9663,9665,9670,9672,9677,9679,9685,9687,9693,9695,9701,9703,9708],{"type":57,"value":9650},"When you only need ",{"type":48,"tag":53,"props":9652,"children":9653},{},[9654],{"type":57,"value":9655},"server → client",{"type":57,"value":9657}," streaming (live counters, notifications, progress, token streams), SSE is simpler than a WebSocket and needs no ",{"type":48,"tag":62,"props":9659,"children":9661},{"className":9660},[],[9662],{"type":57,"value":5109},{"type":57,"value":9664}," method or extra library: a plain ",{"type":48,"tag":62,"props":9666,"children":9668},{"className":9667},[],[9669],{"type":57,"value":4016},{"type":57,"value":9671}," handler returns a ",{"type":48,"tag":62,"props":9673,"children":9675},{"className":9674},[],[9676],{"type":57,"value":377},{"type":57,"value":9678}," whose body is a ",{"type":48,"tag":62,"props":9680,"children":9682},{"className":9681},[],[9683],{"type":57,"value":9684},"ReadableStream",{"type":57,"value":9686}," with ",{"type":48,"tag":62,"props":9688,"children":9690},{"className":9689},[],[9691],{"type":57,"value":9692},"Content-Type: text\u002Fevent-stream",{"type":57,"value":9694},", and the runtime holds it open as long as bytes flow. The browser consumes it with ",{"type":48,"tag":62,"props":9696,"children":9698},{"className":9697},[],[9699],{"type":57,"value":9700},"EventSource",{"type":57,"value":9702},", which ",{"type":48,"tag":53,"props":9704,"children":9705},{},[9706],{"type":57,"value":9707},"reconnects on its own",{"type":57,"value":9709}," — so there's no client backoff to write.",{"type":48,"tag":92,"props":9711,"children":9713},{"className":615,"code":9712,"language":617,"meta":97,"style":97},"\u002F\u002F src\u002Findex.ts — minimal SSE endpoint\nconst encoder = new TextEncoder();\nexport default {\n  fetch: () =>\n    new Response(\n      new ReadableStream\u003CUint8Array>({\n        start(controller) {\n          controller.enqueue(encoder.encode(\"data: hello\\n\\n\"));\n          const t = setInterval(() => controller.enqueue(encoder.encode(\": ping\\n\\n\")), 25_000);\n          return () => clearInterval(t); \u002F\u002F fires when the client disconnects\n        },\n      }),\n      { headers: { \"Content-Type\": \"text\u002Fevent-stream\", \"Cache-Control\": \"no-cache, no-transform\" } },\n    ),\n};\n",[9714],{"type":48,"tag":62,"props":9715,"children":9716},{"__ignoreMap":97},[9717,9725,9758,9773,9793,9809,9843,9868,9933,10036,10079,10087,10102,10194,10206],{"type":48,"tag":103,"props":9718,"children":9719},{"class":105,"line":106},[9720],{"type":48,"tag":103,"props":9721,"children":9722},{"style":627},[9723],{"type":57,"value":9724},"\u002F\u002F src\u002Findex.ts — minimal SSE endpoint\n",{"type":48,"tag":103,"props":9726,"children":9727},{"class":105,"line":633},[9728,9732,9737,9741,9745,9750,9754],{"type":48,"tag":103,"props":9729,"children":9730},{"style":1188},[9731],{"type":57,"value":1191},{"type":48,"tag":103,"props":9733,"children":9734},{"style":649},[9735],{"type":57,"value":9736}," encoder ",{"type":48,"tag":103,"props":9738,"children":9739},{"style":643},[9740],{"type":57,"value":1201},{"type":48,"tag":103,"props":9742,"children":9743},{"style":643},[9744],{"type":57,"value":1235},{"type":48,"tag":103,"props":9746,"children":9747},{"style":709},[9748],{"type":57,"value":9749}," TextEncoder",{"type":48,"tag":103,"props":9751,"children":9752},{"style":649},[9753],{"type":57,"value":1376},{"type":48,"tag":103,"props":9755,"children":9756},{"style":643},[9757],{"type":57,"value":682},{"type":48,"tag":103,"props":9759,"children":9760},{"class":105,"line":685},[9761,9765,9769],{"type":48,"tag":103,"props":9762,"children":9763},{"style":637},[9764],{"type":57,"value":701},{"type":48,"tag":103,"props":9766,"children":9767},{"style":637},[9768],{"type":57,"value":706},{"type":48,"tag":103,"props":9770,"children":9771},{"style":643},[9772],{"type":57,"value":740},{"type":48,"tag":103,"props":9774,"children":9775},{"class":105,"line":695},[9776,9780,9784,9788],{"type":48,"tag":103,"props":9777,"children":9778},{"style":709},[9779],{"type":57,"value":5154},{"type":48,"tag":103,"props":9781,"children":9782},{"style":643},[9783],{"type":57,"value":612},{"type":48,"tag":103,"props":9785,"children":9786},{"style":643},[9787],{"type":57,"value":5657},{"type":48,"tag":103,"props":9789,"children":9790},{"style":1188},[9791],{"type":57,"value":9792}," =>\n",{"type":48,"tag":103,"props":9794,"children":9795},{"class":105,"line":724},[9796,9801,9805],{"type":48,"tag":103,"props":9797,"children":9798},{"style":643},[9799],{"type":57,"value":9800},"    new",{"type":48,"tag":103,"props":9802,"children":9803},{"style":709},[9804],{"type":57,"value":4368},{"type":48,"tag":103,"props":9806,"children":9807},{"style":649},[9808],{"type":57,"value":6733},{"type":48,"tag":103,"props":9810,"children":9811},{"class":105,"line":743},[9812,9817,9822,9826,9831,9835,9839],{"type":48,"tag":103,"props":9813,"children":9814},{"style":643},[9815],{"type":57,"value":9816},"      new",{"type":48,"tag":103,"props":9818,"children":9819},{"style":709},[9820],{"type":57,"value":9821}," ReadableStream",{"type":48,"tag":103,"props":9823,"children":9824},{"style":643},[9825],{"type":57,"value":5193},{"type":48,"tag":103,"props":9827,"children":9828},{"style":110},[9829],{"type":57,"value":9830},"Uint8Array",{"type":48,"tag":103,"props":9832,"children":9833},{"style":643},[9834],{"type":57,"value":5202},{"type":48,"tag":103,"props":9836,"children":9837},{"style":649},[9838],{"type":57,"value":716},{"type":48,"tag":103,"props":9840,"children":9841},{"style":643},[9842],{"type":57,"value":721},{"type":48,"tag":103,"props":9844,"children":9845},{"class":105,"line":760},[9846,9851,9855,9860,9864],{"type":48,"tag":103,"props":9847,"children":9848},{"style":728},[9849],{"type":57,"value":9850},"        start",{"type":48,"tag":103,"props":9852,"children":9853},{"style":643},[9854],{"type":57,"value":716},{"type":48,"tag":103,"props":9856,"children":9857},{"style":1426},[9858],{"type":57,"value":9859},"controller",{"type":48,"tag":103,"props":9861,"children":9862},{"style":643},[9863],{"type":57,"value":894},{"type":48,"tag":103,"props":9865,"children":9866},{"style":643},[9867],{"type":57,"value":740},{"type":48,"tag":103,"props":9869,"children":9870},{"class":105,"line":777},[9871,9876,9880,9885,9889,9894,9898,9903,9907,9911,9916,9921,9925,9929],{"type":48,"tag":103,"props":9872,"children":9873},{"style":649},[9874],{"type":57,"value":9875},"          controller",{"type":48,"tag":103,"props":9877,"children":9878},{"style":643},[9879],{"type":57,"value":158},{"type":48,"tag":103,"props":9881,"children":9882},{"style":709},[9883],{"type":57,"value":9884},"enqueue",{"type":48,"tag":103,"props":9886,"children":9887},{"style":728},[9888],{"type":57,"value":716},{"type":48,"tag":103,"props":9890,"children":9891},{"style":649},[9892],{"type":57,"value":9893},"encoder",{"type":48,"tag":103,"props":9895,"children":9896},{"style":643},[9897],{"type":57,"value":158},{"type":48,"tag":103,"props":9899,"children":9900},{"style":709},[9901],{"type":57,"value":9902},"encode",{"type":48,"tag":103,"props":9904,"children":9905},{"style":728},[9906],{"type":57,"value":716},{"type":48,"tag":103,"props":9908,"children":9909},{"style":643},[9910],{"type":57,"value":677},{"type":48,"tag":103,"props":9912,"children":9913},{"style":116},[9914],{"type":57,"value":9915},"data: hello",{"type":48,"tag":103,"props":9917,"children":9918},{"style":649},[9919],{"type":57,"value":9920},"\\n\\n",{"type":48,"tag":103,"props":9922,"children":9923},{"style":643},[9924],{"type":57,"value":677},{"type":48,"tag":103,"props":9926,"children":9927},{"style":728},[9928],{"type":57,"value":1473},{"type":48,"tag":103,"props":9930,"children":9931},{"style":643},[9932],{"type":57,"value":682},{"type":48,"tag":103,"props":9934,"children":9935},{"class":105,"line":786},[9936,9941,9946,9950,9954,9958,9962,9966,9971,9975,9979,9983,9987,9991,9995,9999,10003,10008,10012,10016,10020,10024,10028,10032],{"type":48,"tag":103,"props":9937,"children":9938},{"style":1188},[9939],{"type":57,"value":9940},"          const",{"type":48,"tag":103,"props":9942,"children":9943},{"style":649},[9944],{"type":57,"value":9945}," t",{"type":48,"tag":103,"props":9947,"children":9948},{"style":643},[9949],{"type":57,"value":1567},{"type":48,"tag":103,"props":9951,"children":9952},{"style":709},[9953],{"type":57,"value":7380},{"type":48,"tag":103,"props":9955,"children":9956},{"style":728},[9957],{"type":57,"value":716},{"type":48,"tag":103,"props":9959,"children":9960},{"style":643},[9961],{"type":57,"value":1376},{"type":48,"tag":103,"props":9963,"children":9964},{"style":1188},[9965],{"type":57,"value":1438},{"type":48,"tag":103,"props":9967,"children":9968},{"style":649},[9969],{"type":57,"value":9970}," controller",{"type":48,"tag":103,"props":9972,"children":9973},{"style":643},[9974],{"type":57,"value":158},{"type":48,"tag":103,"props":9976,"children":9977},{"style":709},[9978],{"type":57,"value":9884},{"type":48,"tag":103,"props":9980,"children":9981},{"style":728},[9982],{"type":57,"value":716},{"type":48,"tag":103,"props":9984,"children":9985},{"style":649},[9986],{"type":57,"value":9893},{"type":48,"tag":103,"props":9988,"children":9989},{"style":643},[9990],{"type":57,"value":158},{"type":48,"tag":103,"props":9992,"children":9993},{"style":709},[9994],{"type":57,"value":9902},{"type":48,"tag":103,"props":9996,"children":9997},{"style":728},[9998],{"type":57,"value":716},{"type":48,"tag":103,"props":10000,"children":10001},{"style":643},[10002],{"type":57,"value":677},{"type":48,"tag":103,"props":10004,"children":10005},{"style":116},[10006],{"type":57,"value":10007},": ping",{"type":48,"tag":103,"props":10009,"children":10010},{"style":649},[10011],{"type":57,"value":9920},{"type":48,"tag":103,"props":10013,"children":10014},{"style":643},[10015],{"type":57,"value":677},{"type":48,"tag":103,"props":10017,"children":10018},{"style":728},[10019],{"type":57,"value":1473},{"type":48,"tag":103,"props":10021,"children":10022},{"style":643},[10023],{"type":57,"value":814},{"type":48,"tag":103,"props":10025,"children":10026},{"style":1296},[10027],{"type":57,"value":7343},{"type":48,"tag":103,"props":10029,"children":10030},{"style":728},[10031],{"type":57,"value":894},{"type":48,"tag":103,"props":10033,"children":10034},{"style":643},[10035],{"type":57,"value":682},{"type":48,"tag":103,"props":10037,"children":10038},{"class":105,"line":822},[10039,10044,10048,10052,10057,10061,10066,10070,10074],{"type":48,"tag":103,"props":10040,"children":10041},{"style":637},[10042],{"type":57,"value":10043},"          return",{"type":48,"tag":103,"props":10045,"children":10046},{"style":643},[10047],{"type":57,"value":5657},{"type":48,"tag":103,"props":10049,"children":10050},{"style":1188},[10051],{"type":57,"value":1438},{"type":48,"tag":103,"props":10053,"children":10054},{"style":709},[10055],{"type":57,"value":10056}," clearInterval",{"type":48,"tag":103,"props":10058,"children":10059},{"style":728},[10060],{"type":57,"value":716},{"type":48,"tag":103,"props":10062,"children":10063},{"style":649},[10064],{"type":57,"value":10065},"t",{"type":48,"tag":103,"props":10067,"children":10068},{"style":728},[10069],{"type":57,"value":894},{"type":48,"tag":103,"props":10071,"children":10072},{"style":643},[10073],{"type":57,"value":2054},{"type":48,"tag":103,"props":10075,"children":10076},{"style":627},[10077],{"type":57,"value":10078}," \u002F\u002F fires when the client disconnects\n",{"type":48,"tag":103,"props":10080,"children":10081},{"class":105,"line":857},[10082],{"type":48,"tag":103,"props":10083,"children":10084},{"style":643},[10085],{"type":57,"value":10086},"        },\n",{"type":48,"tag":103,"props":10088,"children":10089},{"class":105,"line":34},[10090,10094,10098],{"type":48,"tag":103,"props":10091,"children":10092},{"style":643},[10093],{"type":57,"value":4850},{"type":48,"tag":103,"props":10095,"children":10096},{"style":649},[10097],{"type":57,"value":894},{"type":48,"tag":103,"props":10099,"children":10100},{"style":643},[10101],{"type":57,"value":2770},{"type":48,"tag":103,"props":10103,"children":10104},{"class":105,"line":874},[10105,10110,10114,10118,10122,10126,10131,10135,10139,10143,10148,10152,10156,10160,10165,10169,10173,10177,10182,10186,10190],{"type":48,"tag":103,"props":10106,"children":10107},{"style":643},[10108],{"type":57,"value":10109},"      {",{"type":48,"tag":103,"props":10111,"children":10112},{"style":728},[10113],{"type":57,"value":4403},{"type":48,"tag":103,"props":10115,"children":10116},{"style":643},[10117],{"type":57,"value":612},{"type":48,"tag":103,"props":10119,"children":10120},{"style":643},[10121],{"type":57,"value":646},{"type":48,"tag":103,"props":10123,"children":10124},{"style":643},[10125],{"type":57,"value":667},{"type":48,"tag":103,"props":10127,"children":10128},{"style":728},[10129],{"type":57,"value":10130},"Content-Type",{"type":48,"tag":103,"props":10132,"children":10133},{"style":643},[10134],{"type":57,"value":677},{"type":48,"tag":103,"props":10136,"children":10137},{"style":643},[10138],{"type":57,"value":612},{"type":48,"tag":103,"props":10140,"children":10141},{"style":643},[10142],{"type":57,"value":667},{"type":48,"tag":103,"props":10144,"children":10145},{"style":116},[10146],{"type":57,"value":10147},"text\u002Fevent-stream",{"type":48,"tag":103,"props":10149,"children":10150},{"style":643},[10151],{"type":57,"value":677},{"type":48,"tag":103,"props":10153,"children":10154},{"style":643},[10155],{"type":57,"value":814},{"type":48,"tag":103,"props":10157,"children":10158},{"style":643},[10159],{"type":57,"value":667},{"type":48,"tag":103,"props":10161,"children":10162},{"style":728},[10163],{"type":57,"value":10164},"Cache-Control",{"type":48,"tag":103,"props":10166,"children":10167},{"style":643},[10168],{"type":57,"value":677},{"type":48,"tag":103,"props":10170,"children":10171},{"style":643},[10172],{"type":57,"value":612},{"type":48,"tag":103,"props":10174,"children":10175},{"style":643},[10176],{"type":57,"value":667},{"type":48,"tag":103,"props":10178,"children":10179},{"style":116},[10180],{"type":57,"value":10181},"no-cache, no-transform",{"type":48,"tag":103,"props":10183,"children":10184},{"style":643},[10185],{"type":57,"value":677},{"type":48,"tag":103,"props":10187,"children":10188},{"style":643},[10189],{"type":57,"value":657},{"type":48,"tag":103,"props":10191,"children":10192},{"style":643},[10193],{"type":57,"value":2635},{"type":48,"tag":103,"props":10195,"children":10196},{"class":105,"line":883},[10197,10202],{"type":48,"tag":103,"props":10198,"children":10199},{"style":649},[10200],{"type":57,"value":10201},"    )",{"type":48,"tag":103,"props":10203,"children":10204},{"style":643},[10205],{"type":57,"value":2770},{"type":48,"tag":103,"props":10207,"children":10208},{"class":105,"line":1480},[10209],{"type":48,"tag":103,"props":10210,"children":10211},{"style":643},[10212],{"type":57,"value":5037},{"type":48,"tag":49,"props":10214,"children":10215},{},[10216,10218,10223,10225,10229,10231,10237,10239,10244,10246,10251,10253,10258,10260,10265,10267,10272,10274,10281],{"type":57,"value":10217},"The same rules as WebSockets apply. ",{"type":48,"tag":53,"props":10219,"children":10220},{},[10221],{"type":57,"value":10222},"Heartbeat:",{"type":57,"value":10224}," a stream stays open only while bytes flow — Neon's window is 15 minutes (",{"type":48,"tag":82,"props":10226,"children":10227},{"href":305},[10228],{"type":57,"value":308},{"type":57,"value":10230},") but proxies are usually far stricter, so emit a ",{"type":48,"tag":62,"props":10232,"children":10234},{"className":10233},[],[10235],{"type":57,"value":10236},": ping\\n\\n",{"type":57,"value":10238}," comment every ~25–30s (shown above) to keep idle streams from being dropped. Keep state in Postgres, and fan out across isolates using one of the ",{"type":48,"tag":82,"props":10240,"children":10241},{"href":7270},[10242],{"type":57,"value":10243},"sync strategies",{"type":57,"value":10245}," (hold a ",{"type":48,"tag":62,"props":10247,"children":10249},{"className":10248},[],[10250],{"type":57,"value":7639},{"type":57,"value":10252}," of stream controllers and ",{"type":48,"tag":62,"props":10254,"children":10256},{"className":10255},[],[10257],{"type":57,"value":9884},{"type":57,"value":10259}," to each). ",{"type":48,"tag":62,"props":10261,"children":10263},{"className":10262},[],[10264],{"type":57,"value":9700},{"type":57,"value":10266}," is GET-only and can't set headers, so authenticate with a ",{"type":48,"tag":62,"props":10268,"children":10270},{"className":10269},[],[10271],{"type":57,"value":5327},{"type":57,"value":10273}," query param or cookie, exactly like the WebSocket case. ",{"type":48,"tag":82,"props":10275,"children":10278},{"href":10276,"rel":10277},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fsse.md",[86],[10279],{"type":57,"value":10280},"references\u002Fsse.md",{"type":57,"value":10282}," has the full pattern — Hono variant, cross-isolate fan-out, wire format, client, and caveats.",{"type":48,"tag":194,"props":10284,"children":10286},{"id":10285},"mcp-servers",[10287],{"type":57,"value":10288},"MCP Servers",{"type":48,"tag":49,"props":10290,"children":10291},{},[10292,10294,10301,10303,10308,10310,10316,10317,10323,10325,10331,10333,10338,10340,10345],{"type":57,"value":10293},"An ",{"type":48,"tag":82,"props":10295,"children":10298},{"href":10296,"rel":10297},"https:\u002F\u002Fmodelcontextprotocol.io",[86],[10299],{"type":57,"value":10300},"MCP",{"type":57,"value":10302}," server is a natural Functions workload: a long-running HTTP handler that exposes tools to AI clients (Cursor, Claude, ChatGPT, agents), with those tools reading and writing the branch's Postgres right next to the compute. MCP's ",{"type":48,"tag":53,"props":10304,"children":10305},{},[10306],{"type":57,"value":10307},"streamable HTTP transport",{"type":57,"value":10309}," is a plain ",{"type":48,"tag":62,"props":10311,"children":10313},{"className":10312},[],[10314],{"type":57,"value":10315},"POST",{"type":57,"value":1410},{"type":48,"tag":62,"props":10318,"children":10320},{"className":10319},[],[10321],{"type":57,"value":10322},"GET",{"type":57,"value":10324}," on a single endpoint (conventionally ",{"type":48,"tag":62,"props":10326,"children":10328},{"className":10327},[],[10329],{"type":57,"value":10330},"\u002Fmcp",{"type":57,"value":10332},"), so it maps onto a function's ",{"type":48,"tag":62,"props":10334,"children":10336},{"className":10335},[],[10337],{"type":57,"value":4016},{"type":57,"value":10339}," handler with no ",{"type":48,"tag":62,"props":10341,"children":10343},{"className":10342},[],[10344],{"type":57,"value":5109},{"type":57,"value":10346}," method or extra protocol.",{"type":48,"tag":49,"props":10348,"children":10349},{},[10350,10352,10363,10365,10376,10378,10383],{"type":57,"value":10351},"The simplest host is a Hono app using the official ",{"type":48,"tag":82,"props":10353,"children":10356},{"href":10354,"rel":10355},"https:\u002F\u002Fgithub.com\u002Fmodelcontextprotocol\u002Ftypescript-sdk",[86],[10357],{"type":48,"tag":62,"props":10358,"children":10360},{"className":10359},[],[10361],{"type":57,"value":10362},"@modelcontextprotocol\u002Fsdk",{"type":57,"value":10364}," plus ",{"type":48,"tag":82,"props":10366,"children":10369},{"href":10367,"rel":10368},"https:\u002F\u002Fgithub.com\u002Fhonojs\u002Fmiddleware\u002Ftree\u002Fmain\u002Fpackages\u002Fmcp",[86],[10370],{"type":48,"tag":62,"props":10371,"children":10373},{"className":10372},[],[10374],{"type":57,"value":10375},"@hono\u002Fmcp",{"type":57,"value":10377},", which bridges the transport to a route. Build the server, register its tools, and create the transport once at module scope, then hand every ",{"type":48,"tag":62,"props":10379,"children":10381},{"className":10380},[],[10382],{"type":57,"value":10330},{"type":57,"value":10384}," request to it:",{"type":48,"tag":92,"props":10386,"children":10388},{"className":615,"code":10387,"language":617,"meta":97,"style":97},"const transport = new StreamableHTTPTransport();\napp.all(\"\u002Fmcp\", async (c) => {\n  if (!mcpServer.isConnected()) await mcpServer.connect(transport);\n  return transport.handleRequest(c);\n});\n",[10389],{"type":48,"tag":62,"props":10390,"children":10391},{"__ignoreMap":97},[10392,10425,10485,10553,10590],{"type":48,"tag":103,"props":10393,"children":10394},{"class":105,"line":106},[10395,10399,10404,10408,10412,10417,10421],{"type":48,"tag":103,"props":10396,"children":10397},{"style":1188},[10398],{"type":57,"value":1191},{"type":48,"tag":103,"props":10400,"children":10401},{"style":649},[10402],{"type":57,"value":10403}," transport ",{"type":48,"tag":103,"props":10405,"children":10406},{"style":643},[10407],{"type":57,"value":1201},{"type":48,"tag":103,"props":10409,"children":10410},{"style":643},[10411],{"type":57,"value":1235},{"type":48,"tag":103,"props":10413,"children":10414},{"style":709},[10415],{"type":57,"value":10416}," StreamableHTTPTransport",{"type":48,"tag":103,"props":10418,"children":10419},{"style":649},[10420],{"type":57,"value":1376},{"type":48,"tag":103,"props":10422,"children":10423},{"style":643},[10424],{"type":57,"value":682},{"type":48,"tag":103,"props":10426,"children":10427},{"class":105,"line":633},[10428,10432,10436,10441,10445,10449,10453,10457,10461,10465,10469,10473,10477,10481],{"type":48,"tag":103,"props":10429,"children":10430},{"style":649},[10431],{"type":57,"value":1388},{"type":48,"tag":103,"props":10433,"children":10434},{"style":643},[10435],{"type":57,"value":158},{"type":48,"tag":103,"props":10437,"children":10438},{"style":709},[10439],{"type":57,"value":10440},"all",{"type":48,"tag":103,"props":10442,"children":10443},{"style":649},[10444],{"type":57,"value":716},{"type":48,"tag":103,"props":10446,"children":10447},{"style":643},[10448],{"type":57,"value":677},{"type":48,"tag":103,"props":10450,"children":10451},{"style":116},[10452],{"type":57,"value":10330},{"type":48,"tag":103,"props":10454,"children":10455},{"style":643},[10456],{"type":57,"value":677},{"type":48,"tag":103,"props":10458,"children":10459},{"style":643},[10460],{"type":57,"value":814},{"type":48,"tag":103,"props":10462,"children":10463},{"style":1188},[10464],{"type":57,"value":1520},{"type":48,"tag":103,"props":10466,"children":10467},{"style":643},[10468],{"type":57,"value":1423},{"type":48,"tag":103,"props":10470,"children":10471},{"style":1426},[10472],{"type":57,"value":1429},{"type":48,"tag":103,"props":10474,"children":10475},{"style":643},[10476],{"type":57,"value":894},{"type":48,"tag":103,"props":10478,"children":10479},{"style":1188},[10480],{"type":57,"value":1438},{"type":48,"tag":103,"props":10482,"children":10483},{"style":643},[10484],{"type":57,"value":740},{"type":48,"tag":103,"props":10486,"children":10487},{"class":105,"line":685},[10488,10492,10496,10500,10505,10509,10514,10519,10523,10528,10532,10536,10540,10545,10549],{"type":48,"tag":103,"props":10489,"children":10490},{"style":637},[10491],{"type":57,"value":7733},{"type":48,"tag":103,"props":10493,"children":10494},{"style":728},[10495],{"type":57,"value":1423},{"type":48,"tag":103,"props":10497,"children":10498},{"style":643},[10499],{"type":57,"value":3215},{"type":48,"tag":103,"props":10501,"children":10502},{"style":649},[10503],{"type":57,"value":10504},"mcpServer",{"type":48,"tag":103,"props":10506,"children":10507},{"style":643},[10508],{"type":57,"value":158},{"type":48,"tag":103,"props":10510,"children":10511},{"style":709},[10512],{"type":57,"value":10513},"isConnected",{"type":48,"tag":103,"props":10515,"children":10516},{"style":728},[10517],{"type":57,"value":10518},"()) ",{"type":48,"tag":103,"props":10520,"children":10521},{"style":637},[10522],{"type":57,"value":1868},{"type":48,"tag":103,"props":10524,"children":10525},{"style":649},[10526],{"type":57,"value":10527}," mcpServer",{"type":48,"tag":103,"props":10529,"children":10530},{"style":643},[10531],{"type":57,"value":158},{"type":48,"tag":103,"props":10533,"children":10534},{"style":709},[10535],{"type":57,"value":8513},{"type":48,"tag":103,"props":10537,"children":10538},{"style":728},[10539],{"type":57,"value":716},{"type":48,"tag":103,"props":10541,"children":10542},{"style":649},[10543],{"type":57,"value":10544},"transport",{"type":48,"tag":103,"props":10546,"children":10547},{"style":728},[10548],{"type":57,"value":894},{"type":48,"tag":103,"props":10550,"children":10551},{"style":643},[10552],{"type":57,"value":682},{"type":48,"tag":103,"props":10554,"children":10555},{"class":105,"line":695},[10556,10560,10565,10569,10574,10578,10582,10586],{"type":48,"tag":103,"props":10557,"children":10558},{"style":637},[10559],{"type":57,"value":1738},{"type":48,"tag":103,"props":10561,"children":10562},{"style":649},[10563],{"type":57,"value":10564}," transport",{"type":48,"tag":103,"props":10566,"children":10567},{"style":643},[10568],{"type":57,"value":158},{"type":48,"tag":103,"props":10570,"children":10571},{"style":709},[10572],{"type":57,"value":10573},"handleRequest",{"type":48,"tag":103,"props":10575,"children":10576},{"style":728},[10577],{"type":57,"value":716},{"type":48,"tag":103,"props":10579,"children":10580},{"style":649},[10581],{"type":57,"value":1429},{"type":48,"tag":103,"props":10583,"children":10584},{"style":728},[10585],{"type":57,"value":894},{"type":48,"tag":103,"props":10587,"children":10588},{"style":643},[10589],{"type":57,"value":682},{"type":48,"tag":103,"props":10591,"children":10592},{"class":105,"line":724},[10593,10597,10601],{"type":48,"tag":103,"props":10594,"children":10595},{"style":643},[10596],{"type":57,"value":889},{"type":48,"tag":103,"props":10598,"children":10599},{"style":649},[10600],{"type":57,"value":894},{"type":48,"tag":103,"props":10602,"children":10603},{"style":643},[10604],{"type":57,"value":682},{"type":48,"tag":49,"props":10606,"children":10607},{},[10608,10610,10615,10616,10623,10625,10632,10634,10640,10641,10647],{"type":57,"value":10609},"Because the function's URL is public, ",{"type":48,"tag":53,"props":10611,"children":10612},{},[10613],{"type":57,"value":10614},"authenticate before connecting the transport",{"type":57,"value":3331},{"type":48,"tag":82,"props":10617,"children":10620},{"href":10618,"rel":10619},"https:\u002F\u002Fbetter-auth.com",[86],[10621],{"type":57,"value":10622},"Better Auth",{"type":57,"value":10624}," covers both OAuth (its MCP plugin makes your app the authorization server so third-party clients self-authorize per the MCP spec) and a simpler API-key \u002F session-JWT check for your own callers. ",{"type":48,"tag":82,"props":10626,"children":10629},{"href":10627,"rel":10628},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fmcp.md",[86],[10630],{"type":57,"value":10631},"references\u002Fmcp.md",{"type":57,"value":10633}," has the full pattern — server with Postgres-backed tools via Drizzle, both Better Auth auth options, and testing with ",{"type":48,"tag":62,"props":10635,"children":10637},{"className":10636},[],[10638],{"type":57,"value":10639},"mcporter",{"type":57,"value":2991},{"type":48,"tag":62,"props":10642,"children":10644},{"className":10643},[],[10645],{"type":57,"value":10646},"add-mcp",{"type":57,"value":158},{"type":48,"tag":194,"props":10649,"children":10651},{"id":10650},"integrations-and-observability",[10652],{"type":57,"value":10653},"Integrations and Observability",{"type":48,"tag":49,"props":10655,"children":10656},{},[10657,10659,10665,10667,10672,10673,10678],{"type":57,"value":10658},"A function is a long-lived Node.js process running a web-standard request\u002Fresponse handler, so standard Node integration SDKs work unchanged. Initialize them once at module load, gated on an env var so local dev and unconfigured branches stay a no-op, and pass secrets via ",{"type":48,"tag":62,"props":10660,"children":10662},{"className":10661},[],[10663],{"type":57,"value":10664},"--env",{"type":57,"value":10666}," or ",{"type":48,"tag":62,"props":10668,"children":10670},{"className":10669},[],[10671],{"type":57,"value":177},{"type":57,"value":2280},{"type":48,"tag":62,"props":10674,"children":10676},{"className":10675},[],[10677],{"type":57,"value":2361},{"type":57,"value":158},{"type":48,"tag":206,"props":10680,"children":10681},{},[10682,10700],{"type":48,"tag":210,"props":10683,"children":10684},{},[10685,10690,10692,10699],{"type":48,"tag":53,"props":10686,"children":10687},{},[10688],{"type":57,"value":10689},"Sentry",{"type":57,"value":10691}," — error monitoring across the HTTP framework, the function runtime, and an agent's own caught\u002Ffallback failures (the long-running case Functions target): see ",{"type":48,"tag":82,"props":10693,"children":10696},{"href":10694,"rel":10695},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fai\u002Fskills\u002Fneon-functions\u002Freferences\u002Fsentry.md",[86],[10697],{"type":57,"value":10698},"references\u002Fsentry.md",{"type":57,"value":158},{"type":48,"tag":210,"props":10701,"children":10702},{},[10703,10708,10710,10715],{"type":48,"tag":53,"props":10704,"children":10705},{},[10706],{"type":57,"value":10707},"Mastra Studio (Mastra Cloud)",{"type":57,"value":10709}," — run a Mastra agent on a function and ship its traces to a Studio project for observability: see ",{"type":48,"tag":82,"props":10711,"children":10713},{"href":3943,"rel":10712},[86],[10714],{"type":57,"value":3947},{"type":57,"value":158},{"type":48,"tag":194,"props":10717,"children":10719},{"id":10718},"neon-documentation",[10720],{"type":57,"value":10721},"Neon Documentation",{"type":48,"tag":49,"props":10723,"children":10724},{},[10725,10727,10733,10735,10741,10743,10749],{"type":57,"value":10726},"The Neon documentation is the source of truth and Functions is evolving rapidly, so always verify against the official docs. Any doc page can be fetched as markdown by appending ",{"type":48,"tag":62,"props":10728,"children":10730},{"className":10729},[],[10731],{"type":57,"value":10732},".md",{"type":57,"value":10734}," to the URL or by requesting ",{"type":48,"tag":62,"props":10736,"children":10738},{"className":10737},[],[10739],{"type":57,"value":10740},"Accept: text\u002Fmarkdown",{"type":57,"value":10742},". Find the right page from the docs index (",{"type":48,"tag":82,"props":10744,"children":10747},{"href":10745,"rel":10746},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fllms.txt",[86],[10748],{"type":57,"value":10745},{"type":57,"value":10750},") and the changelog announcements.",{"type":48,"tag":194,"props":10752,"children":10754},{"id":10753},"further-reading",[10755],{"type":57,"value":10756},"Further Reading",{"type":48,"tag":206,"props":10758,"children":10759},{},[10760,10769,10778,10787,10796,10805,10814],{"type":48,"tag":210,"props":10761,"children":10762},{},[10763],{"type":48,"tag":82,"props":10764,"children":10767},{"href":10765,"rel":10766},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Foverview.md",[86],[10768],{"type":57,"value":10765},{"type":48,"tag":210,"props":10770,"children":10771},{},[10772],{"type":48,"tag":82,"props":10773,"children":10776},{"href":10774,"rel":10775},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fget-started.md",[86],[10777],{"type":57,"value":10774},{"type":48,"tag":210,"props":10779,"children":10780},{},[10781],{"type":48,"tag":82,"props":10782,"children":10785},{"href":10783,"rel":10784},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fdeploy.md",[86],[10786],{"type":57,"value":10783},{"type":48,"tag":210,"props":10788,"children":10789},{},[10790],{"type":48,"tag":82,"props":10791,"children":10794},{"href":10792,"rel":10793},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fenvironment-variables.md",[86],[10795],{"type":57,"value":10792},{"type":48,"tag":210,"props":10797,"children":10798},{},[10799],{"type":48,"tag":82,"props":10800,"children":10803},{"href":10801,"rel":10802},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Freference\u002Fneon-ts.md",[86],[10804],{"type":57,"value":10801},{"type":48,"tag":210,"props":10806,"children":10807},{},[10808],{"type":48,"tag":82,"props":10809,"children":10812},{"href":10810,"rel":10811},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Freference\u002Fruntime-limits.md",[86],[10813],{"type":57,"value":10810},{"type":48,"tag":210,"props":10815,"children":10816},{},[10817],{"type":48,"tag":82,"props":10818,"children":10821},{"href":10819,"rel":10820},"https:\u002F\u002Fneon.com\u002Fdocs\u002Fcompute\u002Ffunctions\u002Fpreview-access.md",[86],[10822],{"type":57,"value":10819},{"type":48,"tag":10824,"props":10825,"children":10826},"style",{},[10827],{"type":57,"value":10828},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":10830,"total":1778},[10831,10848,10862,10873,10889,10901,10913,10928,10938,10957,10972,10981],{"slug":10832,"name":10832,"fn":10833,"description":10834,"org":10835,"tags":10836,"stars":10845,"repoUrl":10846,"updatedAt":10847},"neon-postgres","build apps with Neon serverless Postgres","Guides and best practices for working with Neon Serverless Postgres. Covers setup, connection methods and drivers, pooled vs direct connections, branching, autoscaling, scale-to-zero, instant restore, read replicas, connection pooling, IP allow lists, and logical replication. Use when users ask about \"Neon setup\", \"connect to Neon\", \"Neon project\", \"DATABASE_URL\", \"serverless Postgres\", \"Neon CLI\", \"neon\", \"Neon MCP\", \"Neon Auth\", \"@neondatabase\u002Fserverless\", \"@neondatabase\u002Fneon-js\", \"scale to zero\", \"Neon autoscaling\", \"Neon read replica\", or \"Neon connection pooling\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10837,10840,10841,10844],{"name":10838,"slug":10839,"type":14},"Database","database",{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},"PostgreSQL","postgresql",{"name":25,"slug":26,"type":14},321,"https:\u002F\u002Fgithub.com\u002Fneondatabase\u002Fwebsite","2026-07-27T06:08:14.168734",{"slug":10849,"name":10849,"fn":10850,"description":10851,"org":10852,"tags":10853,"stars":10859,"repoUrl":10860,"updatedAt":10861},"add-neon-docs","add Neon docs to project AI docs","Use this skill when the user asks to add documentation, add docs, add references, or install documentation about Neon. Adds Neon best practices reference links to project AI documentation (CLAUDE.md, AGENTS.md, or Cursor rules). Does not install packages or modify code.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10854,10855,10858],{"name":10838,"slug":10839,"type":14},{"name":10856,"slug":10857,"type":14},"Documentation","documentation",{"name":9,"slug":8,"type":14},86,"https:\u002F\u002Fgithub.com\u002Fneondatabase\u002Fai-rules","2026-04-06T18:38:53.722898",{"slug":10863,"name":10863,"fn":10864,"description":10865,"org":10866,"tags":10867,"stars":10859,"repoUrl":10860,"updatedAt":10872},"neon-auth","set up Neon Auth for apps","Sets up Neon Auth for your application. Configures authentication, creates auth routes, and generates UI components. Use when adding authentication to Next.js, React SPA, or Node.js projects.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10868,10870,10871],{"name":10869,"slug":4527,"type":14},"Auth",{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},"2026-04-06T18:38:52.386193",{"slug":10874,"name":10874,"fn":10875,"description":10876,"org":10877,"tags":10878,"stars":10859,"repoUrl":10860,"updatedAt":10888},"neon-drizzle","set up Drizzle ORM with Neon","Creates a fully functional Drizzle ORM setup with a provisioned Neon database. Installs dependencies, provisions database credentials, configures connections, generates schemas, and runs migrations. Results in working code that can immediately connect to and query the database. Use when creating new projects with Drizzle, adding ORM to existing applications, or modifying database schemas.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10879,10880,10883,10884,10887],{"name":10838,"slug":10839,"type":14},{"name":10881,"slug":10882,"type":14},"Drizzle","drizzle",{"name":9,"slug":8,"type":14},{"name":10885,"slug":10886,"type":14},"ORM","orm",{"name":10842,"slug":10843,"type":14},"2026-04-06T18:38:56.217495",{"slug":10890,"name":10890,"fn":10891,"description":10892,"org":10893,"tags":10894,"stars":10859,"repoUrl":10860,"updatedAt":10900},"neon-js","set up the Neon JS SDK for auth and queries","Sets up the full Neon JS SDK with unified auth and PostgREST-style database queries. Configures auth client, data client, and type generation. Use when building apps that need both authentication and database access in one SDK.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10895,10896,10897,10898],{"name":10869,"slug":4527,"type":14},{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},{"name":10899,"slug":617,"type":14},"TypeScript","2026-04-06T18:38:51.116041",{"slug":10902,"name":10902,"fn":10903,"description":10904,"org":10905,"tags":10906,"stars":10859,"repoUrl":10860,"updatedAt":10912},"neon-serverless","configure Neon serverless driver","Configures Neon Serverless Driver for Next.js, Vercel Edge Functions, AWS Lambda, and other serverless environments. Installs @neondatabase\u002Fserverless, sets up environment variables, and creates working API route examples with TypeScript types. Use when users need to connect their application to Neon, fetch or query data from a Neon database, integrate Neon with Next.js or serverless frameworks, or set up database access in edge\u002Fserverless environments where traditional PostgreSQL clients don't work.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10907,10908,10909,10910,10911],{"name":10838,"slug":10839,"type":14},{"name":28,"slug":29,"type":14},{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},{"name":25,"slug":26,"type":14},"2026-04-06T18:38:54.97085",{"slug":10914,"name":10914,"fn":10915,"description":10916,"org":10917,"tags":10918,"stars":10859,"repoUrl":10860,"updatedAt":10927},"neon-toolkit","create ephemeral Neon databases for testing","Creates and manages ephemeral Neon databases for testing, CI\u002FCD pipelines, and isolated development environments. Use when building temporary databases for automated tests or rapid prototyping.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10919,10922,10923,10924],{"name":10920,"slug":10921,"type":14},"CI\u002FCD","cicd",{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},{"name":10925,"slug":10926,"type":14},"Testing","testing","2026-04-06T18:38:57.490782",{"slug":10929,"name":10929,"fn":10930,"description":10931,"org":10932,"tags":10933,"stars":30,"repoUrl":31,"updatedAt":10937},"claimable-postgres","provision temporary Postgres databases","Provision instant temporary Postgres databases via Claimable Postgres by Neon (neon.new) with no login, signup, or credit card. Supports REST API, CLI, and SDK. Use when users ask for a quick Postgres environment, a throwaway DATABASE_URL for prototyping\u002Ftests, or \"just give me a DB now\". Triggers include: \"quick postgres\", \"temporary postgres\", \"no signup database\", \"no credit card database\", \"instant DATABASE_URL\", \"npx neon-new\", \"neon.new\", \"neon.new API\", \"claimable postgres API\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10934,10935,10936],{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},"2026-07-27T06:07:56.160588",{"slug":8,"name":8,"fn":10939,"description":10940,"org":10941,"tags":10942,"stars":30,"repoUrl":31,"updatedAt":10956},"build applications on the Neon platform","Overview of the Neon platform for apps and agents, spanning Postgres, Auth, the Data API, Object Storage, Compute Functions, and the AI Gateway. Start here to route to the right Neon skill, set up the CLI or MCP server, and follow the branch-first workflow. Use when \"Neon\" is mentioned, or when any of its individual capabilities are the trigger: \"object storage\" or \"S3\", \"buckets\", \"serverless functions\", \"AI gateway\", \"call an LLM\", \"postgres\", \"database\", or \"backend\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10943,10946,10949,10950,10951,10952,10953],{"name":10944,"slug":10945,"type":14},"AI Infrastructure","ai-infrastructure",{"name":10947,"slug":10948,"type":14},"Authentication","authentication",{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},{"name":25,"slug":26,"type":14},{"name":10954,"slug":10955,"type":14},"Storage","storage","2026-07-27T06:08:01.383115",{"slug":2978,"name":2978,"fn":10958,"description":10959,"org":10960,"tags":10961,"stars":30,"repoUrl":31,"updatedAt":10971},"call LLMs via Neon AI Gateway","One API and one credential for frontier and open-source LLMs, built into your Neon branch and powered by Databricks. Use when a user wants to call an LLM, add AI\u002Fchat\u002Fan agent to their app, route between model providers (OpenAI, Anthropic, Google\u002FGemini, Meta, Alibaba, DeepSeek), or avoid juggling separate provider API keys and accounts — especially when they already use Neon and want AI requests to branch with their project. Works with the OpenAI SDK, Anthropic SDK, google-genai, the Vercel AI SDK, and Mastra by changing only the base URL. Triggers include \"call an LLM\", \"add AI to my app\", \"chat completion\", \"model routing\", \"LLM proxy\u002Fgateway\", \"one API for all models\", \"use Claude\u002FGPT\u002FGemini\", \"AI SDK\", \"Mastra agent\", \"Neon AI Gateway\", and \"log\u002Frate-limit AI calls\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10962,10963,10964,10967,10970],{"name":10944,"slug":10945,"type":14},{"name":22,"slug":23,"type":14},{"name":10965,"slug":10966,"type":14},"Databricks","databricks",{"name":10968,"slug":10969,"type":14},"LLM","llm",{"name":9,"slug":8,"type":14},"2026-07-27T06:08:00.288175",{"slug":4,"name":4,"fn":5,"description":6,"org":10973,"tags":10974,"stars":30,"repoUrl":31,"updatedAt":32},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10975,10976,10977,10978,10979,10980],{"name":22,"slug":23,"type":14},{"name":16,"slug":17,"type":14},{"name":28,"slug":29,"type":14},{"name":9,"slug":8,"type":14},{"name":19,"slug":20,"type":14},{"name":25,"slug":26,"type":14},{"slug":2971,"name":2971,"fn":10982,"description":10983,"org":10984,"tags":10985,"stars":30,"repoUrl":31,"updatedAt":10992},"manage Neon object storage","S3-compatible object storage that branches with your Neon project, so files and the database stay in sync across every branch. Use when a user wants object storage, a bucket, blob\u002Ffile storage, or somewhere to put uploads, images, documents, avatars, or user-generated files for their app or agent — especially when they already use (or are setting up) Neon Postgres and don't want to add a separate storage provider like AWS S3, Cloudflare R2, or Supabase Storage. Triggers include \"object storage\", \"bucket\", \"blob storage\", \"file storage\", \"store uploads\u002Fimages\u002Ffiles\", \"S3-compatible storage\", \"presigned URL\", \"where do I put files\", \"Neon Object Storage\", \"Neon Storage\", and \"storage that branches with my database\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10986,10987,10990,10991],{"name":10838,"slug":10839,"type":14},{"name":10988,"slug":10989,"type":14},"File Storage","file-storage",{"name":9,"slug":8,"type":14},{"name":10954,"slug":10955,"type":14},"2026-07-27T06:07:57.150892",{"items":10994,"total":760},[10995,11001,11011,11019,11028,11035,11052],{"slug":10929,"name":10929,"fn":10930,"description":10931,"org":10996,"tags":10997,"stars":30,"repoUrl":31,"updatedAt":10937},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[10998,10999,11000],{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},{"slug":8,"name":8,"fn":10939,"description":10940,"org":11002,"tags":11003,"stars":30,"repoUrl":31,"updatedAt":10956},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[11004,11005,11006,11007,11008,11009,11010],{"name":10944,"slug":10945,"type":14},{"name":10947,"slug":10948,"type":14},{"name":10838,"slug":10839,"type":14},{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},{"name":25,"slug":26,"type":14},{"name":10954,"slug":10955,"type":14},{"slug":2978,"name":2978,"fn":10958,"description":10959,"org":11012,"tags":11013,"stars":30,"repoUrl":31,"updatedAt":10971},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[11014,11015,11016,11017,11018],{"name":10944,"slug":10945,"type":14},{"name":22,"slug":23,"type":14},{"name":10965,"slug":10966,"type":14},{"name":10968,"slug":10969,"type":14},{"name":9,"slug":8,"type":14},{"slug":4,"name":4,"fn":5,"description":6,"org":11020,"tags":11021,"stars":30,"repoUrl":31,"updatedAt":32},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[11022,11023,11024,11025,11026,11027],{"name":22,"slug":23,"type":14},{"name":16,"slug":17,"type":14},{"name":28,"slug":29,"type":14},{"name":9,"slug":8,"type":14},{"name":19,"slug":20,"type":14},{"name":25,"slug":26,"type":14},{"slug":2971,"name":2971,"fn":10982,"description":10983,"org":11029,"tags":11030,"stars":30,"repoUrl":31,"updatedAt":10992},{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[11031,11032,11033,11034],{"name":10838,"slug":10839,"type":14},{"name":10988,"slug":10989,"type":14},{"name":9,"slug":8,"type":14},{"name":10954,"slug":10955,"type":14},{"slug":11036,"name":11036,"fn":11037,"description":11038,"org":11039,"tags":11040,"stars":30,"repoUrl":31,"updatedAt":11051},"neon-postgres-branches","manage Neon PostgreSQL database branches","Choose and create the right Neon branch type for testing and development. Use when users ask about Neon branching, migration testing with real data, isolated test environments, schema-only branch workflows for sensitive data, resetting a branch from its parent, branch expiration and CI\u002FCD branch lifecycles, or branch creation via Neon CLI or Neon MCP. Triggers include \"Neon branch\", \"test migrations safely\", \"branch production data\", \"schema-only branch\", \"reset branch\", \"branch per PR\" and \"sensitive data testing\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[11041,11042,11045,11048,11049,11050],{"name":10838,"slug":10839,"type":14},{"name":11043,"slug":11044,"type":14},"DevOps","devops",{"name":11046,"slug":11047,"type":14},"Migration","migration",{"name":9,"slug":8,"type":14},{"name":10842,"slug":10843,"type":14},{"name":10925,"slug":10926,"type":14},"2026-07-27T06:07:55.162249",{"slug":11053,"name":11053,"fn":11054,"description":11055,"org":11056,"tags":11057,"stars":30,"repoUrl":31,"updatedAt":11066},"neon-postgres-egress-optimizer","diagnose and fix Postgres egress costs","Diagnose and fix excessive Postgres egress (network data transfer) in a codebase. Use when a user mentions high database bills, unexpected data transfer costs, network transfer charges, egress spikes, \"why is my Neon bill so high\", \"database costs jumped\", SELECT * optimization, query overfetching, reduce Neon costs, optimize database usage, or wants to reduce data sent from their database to their application. Also use when reviewing query patterns for cost efficiency, even if the user doesn't explicitly mention egress or data transfer.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":11},[11058,11061,11062,11065],{"name":11059,"slug":11060,"type":14},"Cost Optimization","cost-optimization",{"name":9,"slug":8,"type":14},{"name":11063,"slug":11064,"type":14},"Performance","performance",{"name":10842,"slug":10843,"type":14},"2026-07-27T06:07:58.159412"]