juspay / streamgres
git clone https://github.com/juspay/streamgres.git
A subscription-native sync engine for PostgreSQL.
—
stars, 24h
—
stars, 7 days
+112
stars, 30 days · #2,058
112
★ total
4
forks · 8 open issues
Star history starts 2026-10-20; the chart appears after the second daily snapshot.
LanguageRust
LicenseApache-2.0
Created2026-10-07 (13d ago)
Last push1d ago
Watchers2
OwnerOrganization
Links
README excerpt
# Streamgres
**A subscription-native sync engine for PostgreSQL.** Clients subscribe to SQL
queries over a WebSocket and keep receiving the *delta*: the rows that entered,
left or changed in their result, as soon as the change commits. No polling, no
re-running queries.
Every subscription is an incrementally maintained view. Each committed change
is routed to exactly the views it affects, at a cost that depends on how many
conditions the write matches, not on how many subscriptions exist.
[code] bash
docker build -f docker/server/Dockerfile -t streamgres .
docker run --env-file .env -p 4848:4848 streamgres
[code] bash
cargo test # unit and scenario tests
cargo run --bin streamgres # demo: SQL in, routed operations and cost counters out
cargo run --release --bin bench # benchmarks: routing, registration, windows, joins
cargo clippy --all-targets
[code] bash
cargo build --release --bin server
XYNE_SYNC_PG_DSN=postgresql://postgres@localhost:5432/xyne_bench \
cargo run --release --bin load -- --connections 200 --duration 60
[code] bash
STREAMGRES_PG_DSN=postgresql://postgres@localhost:5432/streamgres cargo test --test pg_live
[code] rust
use std::rc::Rc;
use streamgres::ivm::SingleTableIVM;
use streamgres::model::*;
use streamgres::parser::{parse_read, parse_write};
use streamgres::sync::{Local, MemoryStorage};
let catalog = Catalog::new(vec![DbTable::new("tickets", ["id"], vec![
DbColumn::new("id", ValueType::Int),
DbColumn::new("status", ValueType::String),
])]);
let storage = Rc::new(MemoryStorage::new());
let mut ivm = Local::new(SingleTableIVM::new(), storage.clone());
let query = parse_read("SELECT * FROM tickets WHERE status = 'OPEN'", &catalog).unwrap();
let (sub, initial) = ivm.register_query(query);
let write = parse_write("INSERT INTO tickets (id, status) VALUES (1, 'OPEN')", &catalog).unwrap();
storage.apply(&write); // commit first,
let deltas = ivm.incremental_update(&write); // then route
[code] text
src/
model/ values, schema, queries, rows and operations
parser/ SQL parser for single-table reads and writes
ivm/ the engine: routing index, frames, windows, join tree
sync/ runtime, storage trait, in-memory store, PostgreSQL reads and change feed
client/ the WebSocket server and Zero protocol, query planning, client groups
bin/ server, bench and load binaries
tests/ scenario tests, live PostgreSQL tests, and a 283-query suite
taken from a production application
scripts/ smoke, end-to-end and load scripts; CI helpers
docker/ the server image
docs/ deployment and observability guides
```
---
## Contributing
See CONTRIBUTING.md for setup, what CI checks and the code
conventions. In short:
- Run `cargo test && cargo clippy --all-targets && cargo run --bin streamgres`
before opening a pull request. The demo must end with every check `PASS`.
- Engine behaviour lives in `src/ivm/`. A change to *what matches* belongs in
`predicate.rs`, with a test alongside it. Routing changes are expected to
move the counters the demo and be