Autoscaling Report: Production databases on Neon use 2.4x less compute and 50% less cost than if they were running on a provisioned platform.
/Neon Functions/Get started

Get started with Neon Functions

Deploy your first Neon Function and call it over HTTP.

Private Preview

This feature is in private preview: it's not ready for production use, and it may be briefly unavailable as we deploy updates. To get access, sign up here.

A function takes a request and returns a web response, running on long-lived Node.js compute next to your database. This guide builds one by hand: define it in neon.ts, run it locally, deploy it, and call it over HTTP.

  1. Prerequisites

    • A Neon account with Functions preview access. See Preview access.
    • The latest neon, installed and authenticated. Functions commands are new and change often during the preview, so upgrade before you start (npm install -g neon@latest).
    • Node.js 20 or later. Deployed functions run on Node.js 24, so use 24 locally for the closest match.

    Functions are available on new projects in AWS us-east-2 only, created on or after June 15, 2026.

    neon init --preview is designed to be run by your AI coding assistant. It outputs structured instructions that guide the agent through setup. To install the Neon Platform (neon) and Neon Functions skills separately:

    npx skills add neondatabase/agent-skills -s neon -s neon-functions
  2. Set up your project

    Create your project directory:

    mkdir my-function && cd my-function

    Then link the directory to your Neon project. There are two ways:

    With an AI coding assistant. Ask it to run neon init --preview. The command returns structured JSON instructions for the full setup: MCP server and agent skills, optional template scaffolding, project linking, and env var pull. Sign-in opens a browser window, and the agent pauses while you complete the OAuth step.

    By hand. Run neon link and select your project and branch when prompted (or pass --project-id). This writes a .neon file and pulls the branch's environment variables into a local .env.

    neon link

    To start from a working example instead, run neon bootstrap. It scaffolds a starter template and links it. Available templates: Hono API, AI SDK agent, Mastra agent, MCP server, Realtime chat (Next.js + WebSockets), and Realtime counter (TanStack Router + SSE), all on Neon Functions. This guide builds the function by hand.

  3. Define your function

    Create neon.ts at your project root. It declares your functions and is what neon dev and neon deploy read:

    neon.ts
    import { defineConfig } from "@neon/config/v1";
    
    export default defineConfig({
      // preview groups features still in beta: functions, AI Gateway, and object-storage buckets.
      preview: {
        functions: {
          // The key is the function's slug:
          // a permanent ID used in CLI commands and the URL.
          hello: {
            name: "My first function", // display label only
            source: "./functions/hello.ts", // path to the handler file
          },
        },
      },
    });

    The slug is permanent: it can't be renamed after the first deploy. See the neon.ts reference for all options.

    Install dependencies:

    npm install @neon/config hono pg
    npm install --save-dev @types/pg

    A function is any module whose default export has a fetch(request) method that returns a Response. That can be an object with a fetch method:

    export default {
      fetch: (request: Request) => new Response('Hello world'),
    };

    Or a bare async function:

    export default async function handler(request: Request) {
      return new Response('Hello world');
    }

    A Hono app exports the object shape, so export default app works directly. For this guide, write a handler that queries Postgres. DATABASE_URL is injected automatically from the linked branch's Postgres database:

    functions/hello.ts
    import { Hono } from 'hono';
    import { Pool } from 'pg';
    
    // Create the pool once at module scope so it's reused across requests.
    const pool = new Pool({ connectionString: process.env.DATABASE_URL, max: 5 });
    const app = new Hono();
    
    app.get('/', async (c) => {
      const { rows } = await pool.query('SELECT version()');
      return c.json(rows[0]);
    });
    
    export default app;
    
    // Optional: drain the pool on shutdown (the platform sends SIGINT).
    process.on('SIGINT', () => {
      pool.end().then(() => process.exit(0));
    });

    Use a connection pool, not the serverless driver

    A function keeps running across requests, so connect to Postgres with a long-lived pg Pool created once at module scope. Don't use @neondatabase/serverless here: it's built for short-lived, edge-style invocations that open a connection per request, which wastes the persistent runtime a function gives you. Use the pooled DATABASE_URL for queries; use DATABASE_URL_UNPOOLED only where you need a dedicated connection (such as LISTEN/NOTIFY).

  4. Develop locally

    neon dev serves all functions declared in neon.ts with hot reload. It injects DATABASE_URL and other Neon env vars from the linked branch. See Environment variables for the full list and how to pull them into a local .env file.

    neon dev

    The terminal prints the URL for each running function:

    Neon Functions dev server
    
      hello                http://localhost:8787
  5. Deploy

    neon deploy reads neon.ts and applies it to the linked branch, deploying every function it declares:

    neon deploy

    The CLI bundles each function with esbuild, uploads it, and waits for the deployment to complete.

    To deploy a single file without a neon.ts, deploy it by slug instead:

    neon functions deploy hello --src functions/hello.ts

    For all deploy options, including the Neon API, see Deploy and manage functions.

  6. Invoke

    Once the deployment reaches completed, retrieve the invocation URL:

    neon functions get hello

    The invocation_url field contains the public URL for your function:

    https://<branch_id>-<slug>.compute.<cell>.us-east-2.aws.neon.tech

    Call it with curl:

    curl https://<branch_id>-hello.compute.<cell>.us-east-2.aws.neon.tech

    The response is a JSON object with your branch's Postgres version:

    { "version": "PostgreSQL 17.x on ..., compiled by gcc ..." }

Need help?

Join our Discord Server to ask questions or see what others are doing with Neon. For paid plan support options, see Support.

Was this page helpful?
Edit on GitHub