JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 1
  • Score
    100M100P100Q39511F
  • License MIT

node-postgres via a WebSocket TCP proxy from neon.tech

Package Exports

  • @jawj/test-serverless
  • @jawj/test-serverless/index.js

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (@jawj/test-serverless) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

@neondatabase/serverless [BETA]

This package from Neon shims the node-postgres pg library to work on serverless runtimes such as Cloudflare Workers and Vercel Edge Functions — places where TCP sockets are not available — via a WebSocket proxy.

Please note: this package also works in web browsers, but in most cases it's not appropriate to publicly deploy that way because it would reveal your Postgres credentials.

How to use it

Where you'd otherwise install pg and @types/pg, instead run npm install @neondatabase/serverless.

Then use it the same way you'd use pg. For example, make your Neon database connection string available in env.DATABASE_URL, then:

import { Client } from '@neondatabase/serverless';

async function whatsTheTimeMrPostgres() {
  const client = new Client(env.DATABASE_URL);
  await client.connect();
  const { rows: [{ now }] } = await client.query('select now();');
  await client.end();
  return now;
}

For a complete usage example on Cloudflare Workers, see https://github.com/neondatabase/serverless-cfworker-demo.

Notes

  • Pooling: in general, serverless platforms don't keep WebSocket connections alive between requests. So it won't generally work to connect a database client (or establish a connection pool) outside of the function that's run on each request. The driver does expose a Pool object, but at this point it is likely to be slower than using Client directly.

  • Cloudflare: brief queries such as the one shown above can generally be run on Cloudflare’s free plan. Queries with larger result sets will typically exceed the 10ms CPU time available to Workers on the free plan: in that case you’ll see a Cloudflare error page and will need to upgrade your Cloudflare service.

Run your own WebSocket proxy

The package comes configured to connect to a Neon database over a secure (wss:) WebSocket.

But you can also run your own WebSocket proxy, and configure it to allow onward connections to your own Postgres instances.

First, you'll need to set up the proxy itself somewhere public-facing (or on localhost for development). See https://github.com/neondatabase/wsproxy for the Go code and instructions.

There are two ways you can secure this.

  1. Set up nginx as a TLS proxy in front of wsproxy. Example shell commands to achieve this are in DEPLOY.md. Onward traffic to Postgres is not secured this way, so Postgres should be running either on the same machine or on one that's reached over a private network.

  2. Use experimental pure-JS Postgres connection encryption via subtls. There's no need for nginx in this scenario, and the Postgres connection is encrypted end-to-end. However, please note that subtls is experimental software and this configuration is therefore not suitable for use in production. You get this form of encryption if you set neonConfig.useSecureWebSocket to false and use ?sslmode=verify-full (or similar) in your connection string.

Configuration

There are two ways to set configuration options:

  1. You can import neonConfig from the package and set global default options on that.
  2. You can also set options per Client instance, using the neonConfig property exposed by the client.

For example:

import { Client, neonConfig } from '@neondatabase/serverless';

// set default options
neonConfig.wsProxy = (host, port) => `my-wsproxy.example.com/v1?address=${host}:${port}`;
neonConfig.rootCerts = `
-----BEGIN CERTIFICATE-----
MIIFazCCA1OgAwIBAgIRAIIQz7DSQONZRGPgu2OCiwAwDQYJKoZIhvcNAQELBQAw ...
-----END CERTIFICATE-----`;

// override default options on individual clients
const client = new Client(env.DATABASE_URL);
client.neonConfig.wsProxy = (host, port) => `my-other-wsproxy.example.com/v1?address=${host}:${port}`;

Then you'll need to set two options on this package — wsProxy and rootCerts. You can do this globally by importing the neonConfig object. For example:

wsProxy

The wsProxy setting should point to the WebSocket proxy you just set up. Usually that will just be a URL host string, but if you want to run different proxies depending on the database host (e.g. to match regions) you can also pass a function with the signature (dbHost: string) => string. For example:

neonConfig.wsProxy = (dbHost) => 
  /[.]eu[.]db[.]example[.]com$/.test(dbHost) ? 
    'my-wsproxy.eu.example.com' : 
      'my-wsproxy.us.example.com';

rootCerts

We bundle our own TLS implementation, which needs to know what root (certificate authority) certificates to trust. The default value of rootCerts is the ISRG Root X1 certificate, which is appropriate for servers secured with Let’s Encrypt.

If you're using any other certificate authority to secure Postgres connections, provide the root certificate(s) in PEM format to the rootCerts option.

TLS version

Please note that the library requires your Postgres installation to support TLS 1.3.

Orientation

The code is at https://github.com/neondatabase/serverless. Most of it is in shims/net/index.ts.

  • To update the npm package, run ./export.sh, then cd dist/npm and npm publish.

  • To run or deploy the test app on Cloudflare, create a .dev.vars file containing DATABASE_URL=postgres://connection_string, run npx wrangler dev --local or npx wrangler publish.

  • To run the test app in a browser, create a .dev.vars file as above, run ./build.sh, start a local server at the repo root, and visit http://localhost:8080/dist/deploy/ (replacing the port number as appropriate).