React Postgres Components

An experiment on deploying remote functions that run inside Postgres using v8, run React SSR, and are easily defined in a rpc/ directory:

rpc/hello-world.tsx

export default function helloWorld () => { const [{version}] = sql`SELECT version()`; // no `await` needed! return <h1>Hello from <em>inside</em> Postgres: {version}</h1>; }

And then using them in frontend SSR like this:

app/page.tsx

import HelloWorld from "@/rpc/hello-world"; export default function Page() { return <Suspense fallback={"Loading…"}> <HelloWorld /> </Suspense>; }

How does it work?

Using esbuild and PLV8 (a Postgres extension that embeds V8), the functions in the rpc/ folder are bundled and inserted into Postgres as part of the Vercel deployment process.

While experimental, this example is a good illustration of Framework-defined Infrastructure. In local dev, the functions are executed in the Node.js runtime and exist in a unified codebase. Upon git push, specialized infrastructure (in this case PLV8 functions) is created.

The function source is extended with a minimalist yet useful runtime:

This resulting bundle is inserted into Postgres as follows:

CREATE OR REPLACE FUNCTION "rpc_hello-world"()
RETURNS text AS $$
  ${functionSource}
$$ LANGUAGE plv8 IMMUTABLE STRICT;

Local development

While Node.js and PLV8 are both based in V8, a good local dev experience needed to account for important differences:

Both of these were solved by leveraging the isolated-vm project transparently during local dev.

For each rpc/ function, a V8 Isolate is created without access to Node.js APIs. Our runtime is loaded on top (like sql and TextEncoder).

To preserve the synchronous plv8.execute API semantics, we use applySyncPromise which pauses the isolate until the promise that dispatches the query is resolved outside of it.

Production

To invoke our functions in production, <HelloWorld /> is issuing a SELECT helloWorld() query to Postgres, which is then streamed to the client via React Server Components.

This makes it such that the Postgres functions are not exposed automatically, and gives us more control and integration with the frontend server side rendering lifecycle.

FAQ

Getting it

The source code is available on rauchg/react-postgres-components and released under the MIT license. Elephant icon by Lima Studio.

To deploy it, you'll need a Vercel Postgres or Neon database linked to the project.