Skip to main content

pgStack

PostgreSQL-native backend. Zero extra containers.

Two containers. That is it.

PostgreSQL + Rust proxy. No GoTrue, no PostgREST, no Realtime, no Kong, no Redis. Run docker compose up -d and your backend is ready.

Real-time SQL queries

The pg_reactive C extension turns any SELECT into a live subscription. Delta delivery via WebSocket. Column-level tracking. No polling.

PostgREST-compatible REST API

Full CRUD with PostgREST filter syntax — eq, gt,ilike, in, embedding via FK. Migrate from Supabase without changing client code.

Auth built-in

Email/password with argon2id, JWT (HS256), OAuth (Google, GitHub), refresh token rotation, and auto-refresh. RLS enforced on every request.

PostgreSQL-backed job queue

Durable background jobs and cron scheduling with no Redis or RabbitMQ. Jobs are rows. Failures are retried. Observability is a SELECT.

TypeScript SDK + CLI

Supabase-compatible @pgstack/sdk with React hooks. CLI for migrations, type generation, and dev environment management.

Get started in minutes

1. Start the stack

npx pgstack init my-app
cd my-app
docker compose up -d

2. Query your data

import { createClient } from '@pgstack/sdk';

const db = createClient(
  'http://127.0.0.1:8080',
  process.env.PGSTACK_ANON_KEY,
);

const { data } = await db.from('todos')
  .select('*')
  .eq('done', false)
  .order('created_at', { ascending: false });

3. Subscribe to live updates

import { useLiveQuery } from '@pgstack/sdk/react';

function TodoList() {
  const { rows, state } = useLiveQuery('active_todos', {
    url: 'ws://127.0.0.1:8080',
    token: session.access_token,
  });
  return rows.map(r => <li>{String(r.title)}</li>);
}

4. Secure with RLS

ALTER TABLE todos ENABLE ROW LEVEL SECURITY;

CREATE POLICY "Users see own todos"
  ON todos FOR ALL
  USING (user_id = auth.uid());

-- Every REST request runs as the
-- authenticated PostgreSQL role.
-- RLS is automatic.