首先:請先使用父層級 neon 技能來瞭解 Neon 概覽、快速入門、Neon 開發最佳實務等內容。
如果尚未安裝 neon 技能,請從 https://neon.com/docs/ai/skills/neon/SKILL.md 取得,或使用以下指令安裝:
npx skills add neondatabase/agent-skills --skill neon
Neon Functions
這是一項公開 beta 功能,目前可在 us-east-2 與 eu-central-1 區域使用。
Neon Functions 是部署在 Neon 分支上的長時運⾏ Node.js HTTP 處理程式。每個函數都會獲得一個公開的 HTTPS URL,與您的資料庫位於同一區域,並且(如果分支有 Postgres)會自動注入 DATABASE_URL。您可以透過您早已熟悉的 Neon CLI、neon.ts 與 API 來進行部署與管理。
使用此技能協助使用者定義、在本機端執行、部署及管理與其資料庫相鄰的函數。最終提供一個已部署的函數及其呼叫 URL、一個可執行的本機 neon dev 迴圈,或來自官方 Neon 文件的精確答案。
使用時機
當工作負載是請/回應處理程式,且需要保持運⾏並與資料相近時,請考慮使用 Neon Functions:
- 超出 Lambda 風格限制的長時運⾏請/回應流程。 每次請求需要進行多次 LLM 呼叫與工具調用,或需要處理圖片/影片生成的代理程式,常常會衝破傳統無伺服器函數約 10-60 秒的執行上限與短暫的串流窗口。Neon Functions 是長時運⾏的:處理程式只需要在 15 分鐘內開始回應即可,而開放的串流只要持續有資料傳輸就能一直保持連線。這為真實的代理程式工作負載提供了充足的空間。
- 無需額外搭配 Redis 的狀態化串流。 由於函數在請求期間保持活躍,它可以託管 SSE 端點或 WebSocket 伺服器,並在處理程序中保持連線開放 — 無需外部狀態儲存(如 Redis)來維持串流的一致性。模組作用域的狀態(例如
pg連線池、記憶體計數器)在同一個隔離環境中的不同請求之間會持續存在。 - 必須與 Postgres 相鄰的運算。 函數與分支資料庫在同一區域運⾏,因此每次查詢不會有跨區域的往返時間。
DATABASE_URL會自動為您注入。 - 與資料一起分支的後端。 每個分支都在自己的 URL 上執行自己版本的函數,並指向自己獨立的資料庫(以及儲存空間、閘道器)狀態。預覽部署、CI 與開發環境各自獲得一個獨立的後端 — 部署到子分支絕不會影響父分支。
- Webhook、機器人與請求後處理。 需要分支出多次資料庫寫入的 Webhook 處理程式、Discord/WebSocket 機器人,以及透過
waitUntil進行的 fire-and-forget 後續處理(例如分析、稽核日誌)都很適合。 - 排程 HTTP 工作。 Function Trigger 會依照 cron 排程對函數發出 POST 請求(
type: "schedule")。使用相同的fetch處理程式,同樣有 15 分鐘的首次位元組時間限制。請參閱 Function Triggers。
如果工作負載是純靜態網站,或需要在目前不支援的區域(us-east-2、eu-central-1)之外運⾏,這並非合適的工具(請參閱 逾時與執行時間限制 與 可用性)。
功能說明
- 長時運⾏且無伺服器 — 專為 WebSocket 伺服器(請參閱 WebSocket 伺服器)、SSE 端點(請參閱 Server-Sent Events (SSE))、長時間的代理程式 HTTP 串流與 API 而建構。閒置時仍會縮減至零。
- Web 標準處理程式 — 一個函數就是任何具有
fetch(request)方法並回傳Response(相容於 Workers/WinterTC)的預設匯出。Hono 應用程式匯出的正是這種形狀,因此export default app可直接運作。基於 Node.js 24 執行,因此所有 Node API 皆可使用。 - 靠近您的資料庫 — 在分支的區域運⾏;當分支有 Postgres 時,
DATABASE_URL會自動注入。 - 可分支 — 每個分支在其自己的 URL 上執行自己版本的函數,並指向自己獨立的狀態。
- 相同的 CLI/API — 透過
neon、neon.ts或 Neon API 進行部署與管理。 - Function Triggers — Neon 會依照 cron 排程對函數發出 POST 請求。請參閱 Function Triggers。
可用性
在進行任何設定之前,請務必確認此前提條件: Neon Functions 是一項公開 beta 功能,目前可在 us-east-2 與 eu-central-1 區域使用。請確認使用者的 Neon 專案位於其中一個區域。在公開 beta 期間,Functions 的使用不計費。
架構:Functions 的定位
Neon(包含 Functions)是後端原語,而非全端應用程式的託管服務。請將您的應用程式託管在 Vercel(或 Netlify,或其他前端/應用程式託管服務)上;Functions 是您後端中需要長時間運⾏、有狀態,且與資料相鄰的部分。它們以兩種方式與該平台組合:
- 為全端應用程式添加 Functions。 您在 Vercel(或 Netlify)上的 Next.js / TanStack Start 應用程式掌管 UI、認證(例如 Neon Auth),並直接與 Lakebase Postgres 與物件儲存溝通。當某個工作負載超出託管服務的短時無伺服器限制時 — 例如 WebSocket 或 SSE 伺服器,或是即將超時的長時間運⾏代理程式 — 只需將那一個部分遷移到 Neon Function 上即可。(請參閱 Functions 作為代理程式後端 以了解用戶端直連模式。)
- 在 Functions 上執行整個後端控制平面。 特別是在前端僅為客戶端的情況下 — 例如 TanStack Router、React Router 的客戶端模式,以及託管在 Vercel 或 Netlify 上的類似 SPA — 客戶端會直接呼叫 Functions。您可以建構 REST API 與請求/回應代理程式、託管 MCP 伺服器,以及執行任何有狀態或需要靠近 Postgres 與物件儲存的功能。
無論採用哪種方式,都應像保護任何獨立 REST API 一樣保護 Function:在處理程式的開頭驗證 JWT 或 API 金鑰(請參閱 Functions 作為代理程式後端 下的 WARNING)。由於 Function 就是您的後端,您可以在託管服務與 Neon 之間遷移部分功能 — 當代理程式或有狀態的 WebSocket 伺服器需要更多執行時間時,將其移到 Function 上;必要時再移回來。
設定
Functions 在 neon.ts 中宣告(請參閱 neon 技能以了解分支優先的工作流程與 neon.ts 基礎知識)。請新增 @neon/config 並在 preview.functions 下依據別名 (slug) 宣告函數:
// neon.ts
import { defineConfig } from "@neon/config/v1";
export default defineConfig({
preview: {
functions: {
todos: {
// slug: ^[a-z0-9]{1,20}$ — 僅限小寫字母與數字,不含連字符號
name: "todo api", // 僅用作顯示標籤
source: "src/index.ts", // 進入點檔案,相對於 neon.ts
},
},
},
});
別名是函數的永久識別碼(它會出現在呼叫 URL 與 CLI 指令中),且在首次部署後無法更改。name 則用於人類可讀的標籤。
一個最小化的函數 — 一個 Hono 應用程式,透過注入的 DATABASE_URL 查詢分支的 Postgres:
// src/index.ts
import { Hono } from "hono";
import { drizzle } from "drizzle-orm/node-postgres";
import { Pool } from "pg";
import { parseEnv } from "@neon/env";
import { attachDatabasePool } from "@neon/functions";
import config from "../neon";
import { todos } from "./db/schema";
const env = parseEnv(config);
const pool = new Pool({ connectionString: env.postgres.databaseUrl, max: 5 });
attachDatabasePool(pool);
const db = drizzle(pool);
const app = new Hono();
app.get("/", (c) => c.text("Neon + Hono + Drizzle"));
app.post("/todos", async (c) => {
const { text } = await c.req.json<{ text: string }>();
const [row] = await db.insert(todos).values({ text }).returning();
return c.json(row, 201);
});
app.get("/todos", async (c) => c.json(await db.select().from(todos)));
export default app;
請在模組作用域建立 pg 連線池(在不同請求之間於同一個隔離環境中重複使用),並將 max 設定為較小的值(例如 5),因為每個隔離環境都有自己的連線池。呼叫 attachDatabasePool(pool) 以避免閒置斷線導致未捕獲的例外狀況 — 請參閱 連線到 Postgres。
parseEnv(config) 需要設定檔所暗示的所有變數。如果函數只透過已池化的 URL 與 Postgres 通訊,可以將範圍限定在該金鑰 — parseEnv 會驗證並僅回傳您要求的內容(金鑰會從您的 neon.ts 自動完成):
const { postgres } = parseEnv(config, ["DATABASE_URL"]); // 不包含未池化的 URL、認證等
const pool = new Pool({ connectionString: postgres.databaseUrl, max: 5 });
attachDatabasePool(pool);
本機開發與部署
neon dev # 提供 neon.ts 中每個函數的即時重新載入;注入 DATABASE_URL 等變數
neon deploy --env <file> # 從 neon.ts 進行完整的偏好的部署;--env 指定用於讀取 Function 環境變數的檔案
請讓 .env 或 .env.local 保持與 preview.functions.*.env 下的每個金鑰同步。neon env pull 僅寫入 Neon 管理的變數;請將 Function 的機密資訊加入該檔案,然後將其作為 --env 傳遞。neon deploy --env <file> 會將該檔案載入 process.env,然後上傳這些值。遺失的值為 undefined,defineConfig 會拋出錯誤。如果您不想寫入某個金鑰,請將其從 neon.ts 中省略。切勿將遺失的 process.env 值強制轉換為空字串:這會上傳 "" 並刪除正式環境的金鑰。空的賦值(KEY=)同樣是 ""。當 TypeScript 需要斷言時,請使用 process.env.X!。
若要部署單一函數而不套用 neon.ts:neon functions deploy <slug> --src src/index.ts(--src 可以接受進入點檔案或包含 index.ts、index.mjs 或 index.js 的目錄)。該指令的 --env 是 KEY=VALUE(可重複),而非檔案路徑。請使用它進行目標明確的環境變數更新。使用 neon functions get <slug> 取得公開 URL(invocation_url 欄位,格式為 https://<branch_id>-<slug>.compute.<cell>.us-east-2.aws.neon.tech)。使用 neon functions list|get|delete 進行管理。
當 neon checkout 建立新分支且存在 neon.ts 時,它會自動套用政策。此建立-套用流程不會載入 --env。如果 Function 環境變數會讀取 process.env,請在 checkout 之後執行 neon deploy --env <file>(如果 checkout 已建立分支,請加上 --update-existing)。對現有分支進行 checkout 不會重新部署;請明確執行 neon deploy --env <file>。
Neon 基礎設施即程式碼 (neon.ts)
設定 中的 preview.functions 區塊是 neon.ts 的一部分,這是 Neon 的基礎設施即程式碼檔案 — 一個 TypeScript 檔案宣告了所有函數(其 source、顯示用 name 與 env),以及任何其他分支服務,並納入版本控制(完整參考請參閱 neon 技能)。請將其視為分支的 Terraform:
neon config status # 印出分支的即時設定(已部署的函數)
neon config plan # 乾執行 apply 將會變更的差異
neon config apply --env <file> # 打包並部署已宣告的函數(neon deploy 是其別名;當 Function 環境變數讀取 process.env 時請傳入 --env)
Functions 是分支作用域的:每個分支在自己的 URL 上執行自己的部署。當存在 neon.ts 時,neon checkout 在建立分支時就會套用政策。此建立-套用流程不會載入 --env。如果 Function 環境變數會讀取 process.env,請在 checkout 之後執行 neon deploy --env <file>。對現有分支進行 checkout 不會重新部署 — 請執行 neon deploy --env <file> 來套用變更。
每個分支的部署微調(例如 runtime)位於 branch 閉包中,以別名為索引,因此可以根據分支而變化,而不影響哪些函數存在:
export default defineConfig({
preview: {
functions: { todos: { name: "todo api", source: "src/index.ts" } },
},
branch: (branch) => ({
preview: { functions: { todos: { runtime: "nodejs24" } } },
}),
});
環境變數
Neon 在執行時期會注入分支作用域的連線字串與服務 URL — 您不需要宣告這些,也無需在部署時傳遞它們:
| 變數 | 備註 |
|---|---|
NEON_BRANCH | 分支名稱(例如 main、preview/foo)。注入每個分支,包括預設分支。 |
DATABASE_URL | 已池化的連線字串。用於大多數查詢。僅當分支有 Postgres 時存在。 |
DATABASE_URL_UNPOOLED | 直接連線。用於遷移、LISTEN/NOTIFY、多回行程式交易。 |
NEON_AUTH_BASE_URL | 當分支啟用了 Neon Auth 時存在。 |
NEON_DATA_API_URL | 當分支啟用了 Data API 時存在。 |
當宣告了物件儲存 (AWS_*) 與 AI Gateway (NEON_AI_GATEWAY_*) 服務時,它們的變數也會被注入 — 請參閱 neon-object-storage 與 neon-ai-gateway 技能。
neon env pull / neon-env run / neon dev 也會將 NEON_BRANCH(以及連線字串)輸出到您的本機開發環境中,因此本機執行會與已部署的執行時期一致。
您自己的機密資訊是每個部署各自的。偏好的路徑:在 neon.ts 中宣告它們,然後執行 neon deploy --env <file>。<file> 是已加入 .gitignore 的檔案,env pull 會寫入該檔案(如果 .env 存在則使用 .env,否則使用 .env.local)。env pull 僅寫入 Neon 管理的變數;請將 Function 的機密資訊加入該檔案。所有宣告的 Function 環境金鑰都必須存在。如果您不想寫入某個金鑰,請將其從 neon.ts 中省略。undefined 表示您要求寫入該金鑰但值不存在(defineConfig 會拋出錯誤)。切勿將遺失的 process.env 值強制轉換為空字串:這會上傳 "" 並刪除正式環境的金鑰。檔案中的空賦值(KEY=)同樣是 ""。如果 TypeScript 需要斷言,請使用 process.env.