Skip to main content

Quickstart

Get Data Stream running locally in 5 minutes.

Prerequisites

  • Docker and Docker Compose
  • Go 1.22+
  • Task (taskfile): brew install go-task

1. Clone and Setup

git clone https://github.com/andrebassi/data-stream.git
cd data-stream

2. Start Infrastructure

# Start PostgreSQL, NATS, Redis, Debezium
task infra:up

# Wait ~30 seconds for services to be healthy
docker compose -f docker-compose.infra.yml ps

Expected output:

NAME          IMAGE                 STATUS
ds-debezium debezium/server:2.5 Up (healthy)
ds-nats nats:2.10-alpine Up (healthy)
ds-postgres postgres:16-alpine Up (healthy)
ds-redis redis:7-alpine Up (healthy)

3. Start Consumer

# Terminal 1: Start the CDC consumer
task consumer:run

Expected output:

=== Data Stream Consumer ===
NATS: nats://localhost:4222
Redis: redis://localhost:6379
Postgres: postgres://datastream:datastream@localhost:5432/datastream
✓ Stream CDC found: DebeziumStream
✓ 4 games loaded from Postgres
✓ Consumer running. Ctrl+C to stop.

4. Start Backend

# Terminal 2: Start the backend API
task backend:run

Expected output:

╔═══════════════════════════════════════════════════════════════╗
║ DATA STREAM BACKEND (Hexagonal Architecture) ║
╠═══════════════════════════════════════════════════════════════╣
║ REST API: ║
║ GET /api/games - List games ║
║ GET /api/latest/:game - Latest result ║
║ GET /api/history/:game - History ║
║ ║
║ WEBSOCKET: ║
║ WS /ws/:game - Stream by game ║
║ ║
║ SSE: ║
║ GET /sse/:game - Stream by game ║
╚═══════════════════════════════════════════════════════════════╝
✓ Server running at http://localhost:3000

5. Test the API

List Games

curl -s http://localhost:3000/api/games | jq
[
{"slug": "crash", "type": "multiplier", "last_round": 512},
{"slug": "double", "type": "color", "last_round": 507},
{"slug": "slot", "type": "slots", "last_round": 506},
{"slug": "wall-street", "type": "trending", "last_round": 508}
]

Get Latest Result

curl -s http://localhost:3000/api/latest/crash | jq
{
"round_id": 512,
"game_slug": "crash",
"game_type": "multiplier",
"finished_at": "2026-01-17T00:45:42Z",
"extras": "{\"point\": \"11.72\"}",
"timestamp": 1768621542123
}

6. Test Real-time Streaming

SSE (Server-Sent Events)

# Terminal 3: Connect to SSE stream
curl -N http://localhost:3000/sse/crash

Output:

event: initial
data: {"round_id":512,"game_slug":"crash",...}

: heartbeat 1705432800

event: message
data: {"round_id":513,"game_slug":"crash",...}

Simulate New Data

# Terminal 4: Insert a new round
task db:simulate

You should see the new round appear in the SSE stream within ~100ms.

7. Open the Dashboard

open http://localhost:3000

The dashboard shows:

  • All games as cards
  • Last result in real-time
  • Auto-updates via SSE

8. Test WebSocket

Open browser DevTools console:

const ws = new WebSocket('ws://localhost:3000/ws/crash');

ws.onmessage = (event) => {
const data = JSON.parse(event.data);
console.log('New round:', data);
};

9. Cleanup

# Stop all services
task infra:down

# Remove volumes (full reset)
task infra:reset

Available Tasks

task -l
TaskDescription
infra:upStart PostgreSQL, NATS, Redis, Debezium
infra:downStop infrastructure
infra:resetReset with volumes
consumer:runRun NATS consumer
backend:runRun backend API
db:simulateGenerate test round
db:generateGenerate 100 rounds
redis:cliConnect to Redis
test:e2eRun end-to-end tests

Next Steps