Skip to main content
scrollr.
ARCHITECTURE / SYSTEM DESIGNGO · RUST · REACT · REDIS

How Scrollr
works.

From source API to your desktop in milliseconds. A decoupled, CDC-driven pipeline built on Go, Rust, React, and Redis.

SEC 01 / THE PIPELINE4 STAGES · SOURCE → SCREEN

The pipeline

Four stages from data source to your screen

01INGEST

Data Sources

TwelveData WebSocket for market data, ESPN API for scores, RSS/Atom feeds for news, Yahoo Fantasy API for leagues.

TwelveData WS
ESPN HTTP
Yahoo API
RSS Feeds
02PROCESS

Ingestion Services

Four independent Rust services collect, normalize, and write data to PostgreSQL. Each runs its own schedule and connection strategy.

Finance :3001
Sports :3002
RSS :3004
Kalshi :3005
03DETECT

PostgreSQL + CDC

All data lands in PostgreSQL. Sequin monitors table changes via CDC (Change Data Capture) and fires webhooks to the core API.

trades
games
rss_items
yahoo_*
04DELIVER

Real-time Delivery

Core API maps each CDC record to a topic in-process and publishes via Redis pub/sub. Every replica fans out to its own SSE clients.

Topic Routing
Redis Pub/Sub
SSE Stream
Per-user
SEC 02 / CDC RECORD FLOW6 HOPS

CDC record flow

How a single data change reaches the right user

01

Rust Service

Writes to PostgreSQL

02

Sequin CDC

Detects row changes

03

Core API

POST /webhooks/sequin

04

Topic Router

record → cdc:{source}:{key}

05

Redis Pub/Sub

events:user:{sub}

06

SSE → Client

Desktop App

SEC 03 / DESIGN PRINCIPLES4 RULES

Design principles

The rules that shape every architectural decision

PR—01Isolated IngestionEach data source has its own Rust ingestion service with an independent schedule, quota budget, and crash blast radius. Widget read APIs live inside the core gateway.
PR—02Zero-trust GatewayCore API validates JWTs at the edge. The one proxied service (Fantasy) never sees tokens — it trusts identity headers injected by the gateway.
PR—03Self-registrationThe Fantasy service registers in Redis on startup with a 30s TTL heartbeat and is discovered dynamically. First-party widget sources are served natively by core.
PR—04Server-authoritative catalogOne catalog defines every widget, served from the API. The desktop fetches it and renders generically, so a new widget ships without a new release.
SEC 04 / TECH STACK6 LAYERS

Tech stack

What powers each layer

Core API

Go 1.25

Fiber v2, pgx, Redis

SSE Hub

Per-user Redis Pub/Sub channels

Logto

Self-hosted OIDC, JWT validation

Ingestion

Rust

tokio async runtime

WebSocket

TwelveData persistent connection

HTTP Polling

ESPN 60s, RSS 5min, Yahoo 120s

Frontend

React 19

Vite 7, TanStack Router

Tailwind v4

daisyUI theme system

Motion

Production-grade animations

Desktop

Tauri v2

Cross-platform native shell

React 19

Multi-window UI

SSE + Polling

Real-time data delivery

Infrastructure

PostgreSQL

Shared DB, natural table isolation

Redis

Cache, Pub/Sub, registration

Sequin

CDC webhooks from PostgreSQL

Deployment

Kubernetes

DigitalOcean DOKS + DOCR

GitHub Actions

Build, deploy, smoke test

nginx + cert-manager

Ingress, TLS

Built and deployed on self-hosted infrastructure