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
| Task | Description |
|---|---|
infra:up | Start PostgreSQL, NATS, Redis, Debezium |
infra:down | Stop infrastructure |
infra:reset | Reset with volumes |
consumer:run | Run NATS consumer |
backend:run | Run backend API |
db:simulate | Generate test round |
db:generate | Generate 100 rounds |
redis:cli | Connect to Redis |
test:e2e | Run end-to-end tests |
Next Steps
- Architecture - Understand the design
- WebSocket Protocol - Bidirectional streaming
- SSE Protocol - Server push
- API Reference - All endpoints
- Fly.io Deployment - Production deployment