Beta
The OptiTech Functions is in Beta. Share your feedback on Discord or via the OptiTech Console.
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 optitech.ts, run it locally, deploy it, and call it over HTTP.
Prerequisites
- A OptiTech project in AWS US East (Ohio) (
aws-us-east-2), the only region where Functions are available during beta. - The latest
optitech, installed and authenticated. Functions commands are new and change often, so upgrade before you start (npm install -g optitech@latest). - Node.js 20 or later. Deployed functions run on Node.js 24, so use 24 locally for the closest match.
optitech init --previewis designed to be run by your AI coding assistant. It outputs structured instructions that guide the agent through setup. To install the OptiTech Platform (optitech) and OptiTech Functions skills separately:npx skills add optitechdatabase/agent-skills -s optitech -s optitech-functions- A OptiTech project in AWS US East (Ohio) (
Set up your project
Create your project directory:
mkdir my-function && cd my-functionThen link the directory to your OptiTech project. There are two ways:
With an AI coding assistant. Ask it to run
optitech 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
optitech linkand select your project and branch when prompted (or pass--project-id). This writes a.optitechfile and pulls the branch's environment variables into a local.env.optitech linkTo start from a working example instead, run
optitech 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 OptiTech Functions. This guide builds the function by hand.Define your function
Create
optitech.tsat your project root. It declares your functions and is whatoptitech devandoptitech deployread:optitech.tsimport { defineConfig } from "@optitech/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 optitech.ts reference for all options.
Install dependencies:
npm install @optitech/config hono pg npm install --save-dev @types/pgA function is any module whose default export has a
fetch(request)method that returns aResponse. That can be an object with afetchmethod: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 appworks directly. For this guide, write a handler that queries Postgres.DATABASE_URLis injected automatically from the linked branch's Postgres database:functions/hello.tsimport { 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
pgPoolcreated once at module scope. Don't use@optitech/serverlesshere: 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 pooledDATABASE_URLfor queries; useDATABASE_URL_UNPOOLEDonly where you need a dedicated connection (such asLISTEN/NOTIFY).Develop locally
optitech devserves all functions declared inoptitech.tswith hot reload. It injectsDATABASE_URLand other OptiTech env vars from the linked branch. See Environment variables for the full list and how to pull them into a local.envfile.optitech devThe terminal prints the URL for each running function:
OptiTech Functions dev server hello http://localhost:8787Deploy
optitech deployreadsoptitech.tsand applies it to the linked branch, deploying every function it declares:optitech deployThe CLI bundles each function with esbuild, uploads it, and waits for the deployment to complete.
To deploy a single file without a
optitech.ts, deploy it by slug instead:optitech functions deploy hello --src functions/hello.tsFor all deploy options, including the OptiTech API, see Deploy and manage functions.
Invoke
Once the deployment reaches
completed, retrieve the invocation URL:optitech functions get helloThe
invocation_urlfield contains the public URL for your function:https://<branch_id>-<slug>.compute.<cell>.us-east-2.aws.optitech.comCall it with curl:
curl https://<branch_id>-hello.compute.<cell>.us-east-2.aws.optitech.comThe 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 OptiTech. For paid plan support options, see Support.