Skip to Content
PostgreSQL ExtensionGetting Started

PostgreSQL Extension Getting Started

This page covers both the release-download path and the usage path after the pg_kalam extension binaries are installed.

If you still need to build or package the extension itself, use the repository guide: pg/README.md .

If you want PostgreSQL with the extension already installed, use the published Docker image: jamals86/pg-kalam .

Download a Release Package

KalamDB publishes a prebuilt PostgreSQL extension package in each GitHub release:

The install example below automatically uses the latest published GitHub release tag.

Important constraints:

  • The published release package currently targets Linux x86_64.
  • The asset name includes the PostgreSQL feature it was built for, such as pg16.
  • The binary must match the PostgreSQL major version of the server where you install it.
  • If you need another platform or PostgreSQL major, build from source with pgrx.

Example install from a release asset:

VERSION="0.4.2-rc2"
ASSET="pg_kalam-${VERSION}-pg16-linux-x86_64.tar.gz"

curl -LO "https://github.com/kalamstack/KalamDB/releases/download/v0.4.2-rc2/${ASSET}"
curl -LO "https://github.com/kalamstack/KalamDB/releases/download/v0.4.2-rc2/SHA256SUMS"

grep "${ASSET}" SHA256SUMS | sha256sum -c -
tar -xzf "${ASSET}"
./pg_kalam-${VERSION}-pg16-linux-x86_64/install.sh "$(command -v pg_config)"

Run with Docker

For local or CI usage, you can run PostgreSQL with pg_kalam preinstalled directly from Docker Hub:

docker run --name pg-kalam \ -e POSTGRES_USER=kalamdb \ -e POSTGRES_PASSWORD=kalamdb123 \ -e POSTGRES_DB=kalamdb \ -p 5433:5432 \ -d jamals86/pg-kalam:latest-pg16

Then connect with psql and install the extension in the database if your init SQL has not already done it:

CREATE EXTENSION IF NOT EXISTS pg_kalam;

Prerequisites

  • PostgreSQL with pg_kalam installed into that exact PostgreSQL instance.
  • A running KalamDB server reachable from PostgreSQL.
  • The KalamDB gRPC endpoint host and port. The default repository examples use 9188.
  • An auth header if your KalamDB server requires one.

1. Create the Extension

Connect to PostgreSQL as a superuser and install the extension into the target database:

CREATE EXTENSION IF NOT EXISTS pg_kalam;

Verify that PostgreSQL sees the extension functions:

SELECT kalam_version(), kalam_compiled_mode();

2. Register the KalamDB Foreign Server

Create a server definition that points PostgreSQL at KalamDB:

CREATE SERVER IF NOT EXISTS kalam_server FOREIGN DATA WRAPPER pg_kalam OPTIONS ( host '127.0.0.1', port '9188', auth_header 'Bearer <your-kalamdb-token>' );

If PostgreSQL runs in Docker on macOS while KalamDB runs on the host machine, use host.docker.internal instead of 127.0.0.1.

3. Create Your First Shared Table

The primary authoring syntax is CREATE TABLE ... USING kalamdb:

CREATE SCHEMA IF NOT EXISTS app; CREATE TABLE app.shared_items ( id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(), title TEXT NOT NULL, value INTEGER, created_at TIMESTAMP DEFAULT NOW() ) USING kalamdb WITH ( type = 'shared', flush_policy = 'rows:1000,interval:60' );

That statement is intercepted by the extension, creates the target namespace and table in KalamDB, and then exposes the PostgreSQL-visible system columns that the extension manages locally.

Any KalamDB table shape that the server accepts can be authored this way from PostgreSQL. The same option names you would use in KalamDB are forwarded through the PostgreSQL WITH (...) clause.

System-column rules for new tables:

  • Do not declare _seq, _userid, or _deleted in the CREATE TABLE ... USING kalamdb column list. pg_kalam rejects that DDL because those columns are managed by the extension.
  • _seq BIGINT is added to every PostgreSQL table surface that pg_kalam creates.
  • _userid TEXT is added only to user tables.
  • _seq is read-only. Treat it as a projected metadata column, not an application-writable field.

4. Query and Mutate Through PostgreSQL

INSERT INTO app.shared_items (id, title, value) VALUES (SNOWFLAKE_ID(), 'Alpha', 10), (SNOWFLAKE_ID(), 'Beta', 20); SELECT id, title, value FROM app.shared_items ORDER BY id; UPDATE app.shared_items SET value = 25 WHERE id = 2; DELETE FROM app.shared_items WHERE id = 1;

5. Use Session Identity for User Tables

User tables are tenant-scoped. Set kalam.user_id in each PostgreSQL session before querying or mutating them:

SET kalam.user_id = 'user-alice'; CREATE TABLE app.profiles ( id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(), name TEXT, age INTEGER ) USING kalamdb WITH ( type = 'user' ); INSERT INTO app.profiles (id, name, age) VALUES (SNOWFLAKE_ID(), 'Alice', 30); INSERT INTO app.profiles (id, name, age, _userid) VALUES (SNOWFLAKE_ID(), 'Bob', 41, 'user-bob'); SELECT id, name, age, _userid, _seq FROM app.profiles ORDER BY _seq;

The tenant scope comes from the PostgreSQL session value unless you explicitly provide _userid in an INSERT.

Current _userid rules:

  • On user tables, omitting _userid uses the current kalam.user_id session value.
  • On user tables, an explicit _userid in INSERT overrides the session value for that inserted row batch.
  • In a multi-row INSERT, every row must use the same _userid value.
  • UPDATE and DELETE still use the session’s kalam.user_id scope. Changing row ownership with UPDATE ... SET _userid = ... is not part of the supported surface.

6. Reuse KalamDB Table Options with WITH (...)

The WITH (...) clause is the main place to express KalamDB table options from PostgreSQL:

CREATE TABLE app.orders ( id BIGINT PRIMARY KEY DEFAULT SNOWFLAKE_ID(), customer_id TEXT NOT NULL, status TEXT DEFAULT 'pending', created_at TIMESTAMP DEFAULT NOW() ) USING kalamdb WITH ( type = 'shared', flush_policy = 'rows:1000,interval:60' );

Use the same option names and values that KalamDB expects. The extension forwards them to the server when it constructs the real KalamDB CREATE TABLE statement.

7. Send Any Statement Directly to KalamDB

When you want to run a KalamDB statement directly, use kalam_exec(...):

SELECT kalam_exec('ALTER TABLE app.orders ADD COLUMN priority INTEGER DEFAULT 0'); SELECT kalam_exec('DROP TABLE app.orders'); SELECT kalam_exec('SELECT * FROM system.tables');

kalam_exec(...) forwards the statement to the KalamDB server as-is.

  • For SELECT statements, it returns a JSON array string.
  • For DDL and DML statements, it returns a JSON string status message.

8. Maintain the Server Definition

Update server options with standard PostgreSQL syntax:

ALTER SERVER kalam_server OPTIONS (SET host 'kalamdb.internal', SET port '9188'); ALTER SERVER kalam_server OPTIONS (ADD auth_header 'Bearer <replacement-token>');

Remove the bridge when you are done:

DROP SERVER kalam_server CASCADE;

Next Steps

Last updated on