Postgres in Workers: Neon’s serverless bridge

Postgres remains a go-to choice for everything from small prototypes to enterprise systems of record. But connecting to it from Cloudflare Workers has always been awkward: Workers don’t support raw TCP, and Postgres connections are expensive to establish and carry significant memory overhead. Neon.tech has built a purpose-made path around those constraints, and it goes beyond basic connectivity—its platform also supports branching databases that work like code branches: instant, cheap, and isolated.

Getting a Worker talking to Postgres

Neon’s @neondatabase/serverless package is designed as a drop-in replacement for pg, the familiar node-postgres library. After setting up a database through Neon’s getting-started flow, you can have a Worker querying Postgres in a few steps:

  1. Scaffold a Worker — Run npx wrangler init neon-cf-demo, accept the defaults, and cd neon-cf-demo.
  2. Install the driver — Run npm install @neondatabase/serverless.
  3. Set the connection string — For production, run npx wrangler secret put DATABASE_URL and paste the connection string from your Neon dashboard (format roughly postgres://user:[email protected]/main). For local development, create a .dev.vars file with DATABASE_URL= followed by the same string.
  4. Replace the code — Swap the contents of src/index.ts with the snippet below.
import { Client } from '@neondatabase/serverless';
interface Env { DATABASE_URL: string; }

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext) {
    const client = new Client(env.DATABASE_URL);
    await client.connect();
    const { rows: [{ now }] } = await client.query('select now();');
    ctx.waitUntil(client.end());  // this doesn’t hold up the response
    return new Response(now);
  }
}

Run npm start to test locally, or npx wrangler publish to deploy globally. A more complete example—showing nearby UNESCO World Heritage sites based on the Worker’s IP geolocation data, sorted with PostGIS nearest-neighbor logic—is available in the project’s GitHub source.

BLOG-1465 Embedded Image - RCeTnJ

That demo pulls request.cf.longitude and request.cf.latitude, then feeds them into a query ordered by the PostGIS distance operator <->:

const { longitude, latitude } = request.cf
const { rows } = await client.query(`
  select 
    id_no, name_en, category,
    st_makepoint($1, $2) <-> location as distance
  from whc_sites_2021
  order by distance limit 10`,
  [longitude, latitude]
);

A spatial index on the location column keeps the query quick, and the returned rows arrive in a straightforward format:

[{
  "id_no": 308,
  "name_en": "Yosemite National Park",
  "category": "Natural",
  "distance": 252970.14782223428
},
{
  "id_no": 134,
  "name_en": "Redwood National and State Parks",
  "category": "Natural",
  "distance": 416334.3926827573
},
/* … */
]

For even lower latency, the results could be cached at coarser granularity—rounding coordinates to roughly one arc minute (about a mile) of longitude and latitude would trade a little precision for a lot of cache hits.

Inside the architecture

Workers’ V8 isolates are fast and light enough for nearly any workload, but the lack of raw TCP support has kept database access out of reach. Neon’s solution stacks three pieces:

  • Platform-level connection pooling — Because Neon separates storage and compute, a one-to-one client-to-connection model isn’t sensible. Pooling is activated from the Settings section of the Neon dashboard.
  • A WebSocket-to-TCP proxy — Neon runs its own Go-based wsproxy, which accepts WebSocket connections from Workers, relays payloads to a Neon-hosted Postgres over plain TCP, and sends responses back.
  • A patched client library — The driver is based on node-postgres with shims for Node.js APIs that don’t exist in Workers. Notably, net.Socket and tls.connect are replaced by code that routes network I/O over the WebSocket. For end-to-end TLS, WolfSSL is compiled to WebAssembly via emscripten, and esbuild bundles everything into the published npm package.
BLOG-1465 Embedded Image - 8HQz03

The @neondatabase/serverless driver is currently in public beta. Both the driver and the proxy are open source, so the same setup can be pointed at Postgres databases hosted anywhere, not just on Neon—details live in the respective repos. The overall result is a fully managed connection path that turns a Workers deployment into a front end for a real relational database with minimal ceremony.