仙kisenon

Serverless / edge driver

Use @kisenon/serverless — or the stock @neondatabase/serverless — against Kisenon over HTTP and WebSocket.

Edge and serverless runtimes — Cloudflare Workers, Vercel Edge, Deno — cannot open raw TCP sockets, so they can't speak the Postgres wire protocol directly. Kisenon endpoints answer this with an HTTP + WebSocket SQL gateway that is wire-compatible with the Neon serverless driver.

The pitch

Install @kisenon/serverless. It is a drop-in swap for the Neon serverless driver, and it is what the examples on this page import.

The stock @neondatabase/serverless package also works against Kisenon, unmodified — same gateway, same wire format, no neonConfig overrides to set. Pick either; there is one difference between them and it is called out under HTTP queries below.

Either way, the only change from a stock Neon setup is the connection host — point DATABASE_URL at your Kisenon endpoint:

postgres://<user>:<password>@<eid>.<region>.kisenon.com/<db>

That is the same host as your regular Postgres connection string — there is no separate serverless hostname. Grab it from the endpoint card in the console, or with keon connection-string <branch> --project <project-id>.

Install

npm i @kisenon/serverless

HTTP queries with neon()

The neon() tagged-template client sends each query as a single HTTPS POST to the endpoint's /sql route. It runs on Web-standard fetch, so it is safe in edge runtimes with no Node net module. Ideal for one-shot queries in a Worker or Edge Function:

import { neon } from "@kisenon/serverless";

export default {
  async fetch(request, env) {
    const sql = neon(env.DATABASE_URL);
    const [row] = await sql`SELECT 1 AS n`;
    return Response.json({ n: row.n });
  },
};

Parameterized queries interpolate through the tag, so sql`SELECT * FROM users WHERE id = ${id}` is sent as a bound parameter, not string-concatenated.

When the SQL text is a string you built rather than a template, use sql.query(text, params):

const rows = await sql.query("SELECT * FROM users WHERE id = $1", [id]);

This is the one place the two packages differ. @neondatabase/serverless v1 also accepts the direct call sql(text, params). @kisenon/serverless@0.1.0 does not — it binds the tagged-template signature only, so a plain string is read character by character and Postgres rejects it with 42601 syntax error. Use sql.query() and both packages behave identically.

Sessions and transactions with Pool / Client

For multi-statement sessions, interactive transactions, or when you need a long-lived connection, use Pool (or Client). These tunnel the Postgres wire protocol over a WebSocket to the endpoint's /v2 route — the WS path is selected automatically, you don't configure it:

import { Pool } from "@kisenon/serverless";

const pool = new Pool({ connectionString: process.env.DATABASE_URL });
const { rows } = await pool.query("SELECT 1");

The full pg-style API works: pool.connect(), client.query('BEGIN'), prepared statements, and so on, all over the one WebSocket.

How it works

Two transports terminate at the regional data plane:

  • HTTP — neon() POSTs to https://<eid>.<region>.kisenon.com/sql with a Neon-Connection-String header; the gateway runs the query and returns the Neon response envelope (command, rowCount, fields, rows). There is also a front-door form https://api.<region>.kisenon.com/sql, where the endpoint is taken from the connection string in the Neon-Connection-String header rather than the host label — api is a reserved front-door label, not an endpoint id.
  • WebSocket — Pool/Client upgrade wss://<eid>.<region>.kisenon.com/v2 and the gateway transparently bridges the raw Postgres wire protocol (startup, auth, query, row data) across the socket. The stock driver's default pipelined-cleartext auth is handled by a shim, so its md5/SCRAM computes work unmodified.

Both land on the same endpoint your TCP postgres:// string reaches, so they share your branch's data, roles, and TLS certificate.

The edge driver authenticates with both md5 and scram-sha-256 — compute roles default to md5 password encryption while newer roles use scram — and the gateway handles both transparently, so you never configure which one your role uses.

Limits and notes

  • Direct or pooled. The driver works over both the direct host and the pooled <eid>-pooler.<region>.kisenon.com host (transaction mode) — pooling is GA and default-on. For the serverless driver's short-lived connections the pooled host is a natural fit. See Connection strings for pooled-vs-direct.
  • Wake from zero. A suspended endpoint wakes on its first request. An HTTP query to a cold endpoint may briefly return 503 with {"code":"endpoint_waking"} and a Retry-After header; the driver retries HTTP requests transparently where applicable, and a held WebSocket upgrade completes once the endpoint is warm. Expect the first request after idle to take a beat longer.
  • TLS is mandatory. The gateway serves a *.<region>.kisenon.com certificate from the public trust store — no custom CA needed.
  • Falling back to the stock driver. @kisenon/serverless@0.1.0 is exercised against the HTTP path — neon(), sql.query(), sql.transaction() and the fullResults envelope. If you hit trouble on the WebSocket path, @neondatabase/serverless is a supported swap and needs no other change: same host, same connection string, same gateway.
Serverless / edge driver · Kisenon