This guide covers the capture pipeline. For live events over WebSocket and
GraphQL, use the
real-time demo
and Real-time subscriptions.
The demo runs the engines standalone. A running standalone process cannot be
attached to VentStream Cloud in place. To use centralized configuration,
visibility, and lifecycle operations, create a managed pipeline and deploy a new
managed agent.
Everything lives in
demo/stack/:
the docker-compose.yml, the seed data, and the two projection specs.
Prerequisites
- Docker + Docker Compose v2 (
docker compose version) - ~4 GB free RAM for the containers
- Free ports:
5544(pg),7474/7687(neo4j),9200(opensearch),5601(dashboards, optional)
Preflight: clean up and check port 9200
Start from a clean demo state so the seed counts and document IDs in this guide are deterministic:-v;
the exact counts below may then differ if you changed or deleted sample data.
The demo must have exclusive access to host port 9200. Check for another
Docker container or local OpenSearch process before continuing:
1. Start the sources + target
--wait blocks until all three pass their healthchecks, so you don’t
have to poll:
docker compose ps.)
First boot pulls images (Postgres, Neo4j Enterprise, OpenSearch). Postgres
seeds itself from
seed/postgres.sql — 200 orders, 5 customers, line
items, and the ventstream_shop publication.2. Seed Neo4j + enable CDC
Postgres is already seeded. Neo4j needs two one-time commands — enable CDC, then load the catalog graph:3. Start the engines
The engines build from source via cargo-chef. Allow 5–10 minutes for the first build, depending on CPU and network speed; later runs are cached and start in seconds.1
STARTING
Process up, source connection opening.
2
BOOTSTRAPPING
Snapshot scan — existing rows/nodes stream into OpenSearch.
3
TAILING
Steady state — live CDC changes flow as they happen.
4. Verify the initial load
customer and items:
category, supplier → region (2 hops), and tags:
The Postgres doc
_id is the fully-qualified table name plus the PK
as a JSON array: shop.orders:["ord-0001"] (URL-encoded above), so a
GET …/_doc/<id> works directly. The Neo4j doc _id is
products_denormalized:<elementId>, so search by a field (above) rather
than guessing the elementId.5. Watch changes propagate
Keep the engine logs visible while you run these. Each change should appear in the log within ~1s and update OpenSearch.- Postgres
- Neo4j
Update a row (1-hop)Rename a customer (1:1 cascade) — every order for Add a line item (1:many cascade)Delete a primary row — items first (FK), then the order:
cust-002 recomposes:Stream it continuously (optional)
To see the pipeline move, fire updates fast and watch the engine react. We stream the statements into a single psql connection (a per-commanddocker exec would cap the rate at the container-exec overhead) and pace
server-side with pg_sleep:
pg_sleep(0.1) — 0.02 for ~20 ms,
or drop it entirely for max throughput. Each update recomputes only that one
document; the dispatcher may combine nearby updates into one sink batch. Swap the WHERE to
order_id='ord-'||lpad((1+floor(random()*200))::int::text,4,'0') to
spread updates across all 200 orders.
6. Optional — inspection UIs
OpenSearch Dashboards
OpenSearch Dashboards
Neo4j Browser
Neo4j Browser
Always on at http://localhost:7474 (user
neo4j, password
ventstream). Explore the source graph:7. Verify data flow
8. Teardown
Next steps
Author a projection
The
orders and products specs, field by field.How fan-out works
Why renaming a category updates 500 docs without exploding.
Use VentStream Cloud
Enroll managed agents and administer pipelines from the dashboard or CLI.
Deploy to Kubernetes
Ship the whole stack with the bundled manifests.