Inspiration

A chip-plant fire in Taiwan. A tanker wedged in the Red Sea. A surprise 8-K dropped after the close. Within minutes, hundreds of stocks reprice — but the wire only ever names one of them. The link between that single headline and the thirty companies it's about to hit lives in an analyst's head, stitched together by hand from terminals, filings, Discord servers, and weather alerts. By the time a person has drawn the map, the move is already priced in.

We wanted to know what it would take for software to draw that map in real time — not a sentiment score or a news summary, but the actual transmission path: headline → direct supplier → their customer → the peer that competes with both, each ranked by how hard the shock travels.

That's really two problems in one. There's a hard analytical problem — walk a supply-chain graph, embed the text, score relevance, and weigh geography, all at once — and a relentless real-time problem — push every new shock to every open screen, instantly, at any scale. Most tools do one of these well and the other badly. Cascade's whole bet is that the clean answer is two databases, each doing the one job it's unbeatable at.

What it does

Cascade is a real-time market-intelligence terminal. A globe pulses with live events from the last few hours — news, SEC filings, earthquakes, shipping signals, social chatter. The left rail is a ranked feed; click any event and the right rail walks its cascade: the downstream tickers, three supply-chain hops deep, each one scored and explained in plain language — "TSM supplies NVDA (direct, weight 0.95); FedEx is a logistics customer of TSM (second hop)."

Features

Live data — eleven sources, one pipeline

  • SEC EDGAR 8-K filings · Marketaux news · RSS newswires · Reddit · Alpha Vantage
  • yfinance price ticks · GDELT geopolitical events
  • USGS earthquakes · NOAA severe-weather alerts · OpenSky flights · AISStream vessel signals

Cascade intelligence

  • Three-hop supply-chain walk over a 1,149-edge graph, ranked by Voyage rerank-2.5
  • Gemini geo-cascade for tickerless events — geopolitics, weather, regulatory — validated against the live company universe
  • Agent society — Critic, Predictor, Memory, ELI5 — running in parallel with deterministic local fallback
  • Cascade synthesis: severity, risk factors, and a plain-English narrative
  • Auto-triggered cascades on magnitude-6 quakes and critical weather alerts
  • PostGIS proximity — every company HQ within 250 km of a disaster

Hybrid search

  • pgvector semantic + tsvector keyword, fused with Reciprocal Rank Fusion and reranked
  • Chart-image search — drop in a chart, find visually similar events (voyage-multimodal)
  • PDF search — drop in a filing, surface matching events

Three ways to see it

  • 3D globe with live event pulses and fresh-arrival shockwaves
  • 2D force-directed cascade graph
  • 3D cascade with hop-by-hop reveal

Real-time, no refresh

  • Server-Sent Events fed by Aurora LISTEN/NOTIFY and DynamoDB Streams
  • Live status pill showing "last event N seconds ago," grounded in server time

Power-user terminal

  • Click-to-drill from node to node, with a breadcrumb trail
  • Compare mode — two cascades side by side
  • Counterfactual mode — "what if this event hadn't happened?"
  • Time machine — rewind the feed up to seven days
  • Per-device memory, watchlists, source filters, and an ELI5 toggle
  • One-click scenario replays and a guided demo tour
  • Kiosk "watch mode" and full keyboard control (⌘K search · G/C/V views · j/k navigate)

Who it's for, and how it makes money

Cascade sells to the people who get paid to see contagion first.

  • Hedge funds & research desks — open a cascade the instant news breaks instead of rebuilding the supply-chain map by hand. Sold per seat.
  • Corporate risk & supply-chain teams — watch their own suppliers and customers light up when a shock lands three hops away. An early-warning system procurement and risk officers don't have today.
  • Active traders — the same engine in a self-serve tier, the funnel that feeds the desks above.

The model is straightforward SaaS:

Tier Price For
Starter \$29 / mo individual traders, self-serve
Pro \$149 / mo power users and small teams
Desk \$499 / seat / mo funds and research desks
Enterprise custom banks and corporates — API, SSO, private data

A Bloomberg Terminal runs roughly \$2,000 a seat per month. Cascade Pro is about one-fifteenth of that — with the one view Bloomberg doesn't ship: the live cascade. In a market-data industry worth more than \$40B a year, a single avoided bad trade or one early supply-chain warning pays for a seat many times over. And because the stack scales to zero when idle, every tier earns from the first customer.

How we built it

The architecture is the idea: one analytical database, one real-time database.

Amazon Aurora PostgreSQL Serverless v2 — the analytical plane (ripple-aurora-pg)

A cascade query needs four things to happen in a single round trip, and Postgres is the one engine where they all compose:

  • pgvector (1024-dim, HNSW) finds events that mean the same thing.
  • tsvector + GIN finds events that name the same ticker. We blend the two with Reciprocal Rank Fusion and rerank the result with Voyage rerank-2.5, so a single search returns both meaning and precision.
  • WITH RECURSIVE walks the 1,149-edge relationships graph outward from the event's tickers. As it hops supplier → customer → peer, it multiplies the edge weights along each path and carries that running number as a plain column — so "how hard does this land downstream" comes straight out of the walk, already ranked.
  • PostGIS (geography(POINT, 4326)) lights up every company HQ within 250 km of a magnitude-6 quake using ST_DWithin.

Aurora is also the live wire. A single AFTER INSERT trigger fires pg_notify, a Vercel Function holds an asyncpg listener open, and new events stream out over Server-Sent Events. No Redis, no queue — the database is the message bus. With min_capacity = 0 ACU and five-minute auto-pause, idle cost is genuinely \$0.

Amazon DynamoDB on-demand — the real-time plane (ripple-dynamodb)

Aurora is built for the hard read; it's the wrong tool for millions of always-on writes and constant per-device lookups. DynamoDB takes three access patterns it serves in single-digit milliseconds at any scale:

  • A live mirror of the event firehose, with Streams switched on — change data capture as a built-in, no polling. Streams flow through an EventBridge Pipe to a Vercel webhook that fans each new event out to every running function, alongside the Aurora live channel.
  • Per-device cascade history, keyed by an anonymous device_id with a 30-day TTL, so cleanup is automatic. It's what lets the Memory agent say "you've opened TSM four times this week, always during Taiwan events."
  • Per-user watchlists, a plain key lookup.

Because billing is on-demand, there's no capacity to size and no ceiling to hit — the read and write paths look identical with one user or a million.

Compute is 100% Vercel

The FastAPI backend runs as Python Serverless Functions (wrapped with mangum), the eleven ingestion workers run as Vercel Cron Jobs, and SSE rides Vercel response streaming. Credentials never touch our code: Vercel injects an x-vercel-oidc-token header on every request, a middleware captures it, and we exchange it through STS AssumeRoleWithWebIdentity for short-lived, per-role credentials — so no static AWS key lives anywhere in the project. Both databases were provisioned straight from the Vercel Marketplace AWS Databases integration, which means the storage configuration lives in the Vercel dashboard.

Gemini powers cascade synthesis, the agent society, and the geo-cascade, called as a plain HTTPS API. Voyage AI provides the voyage-4 embeddings and the rerank-2.5 cross-encoder.

Built to scale

Scale is designed in, not bolted on. The three things that break a real-time app at a million users have nowhere to break here:

  • Compute never saturates. Stateless Vercel Functions spin up per request at the edge — a thousand users or a million is the same architecture, just more instances. No pool to exhaust, no box to topple.
  • The database has no write ceiling. DynamoDB on-demand shards per-device history by device_id across millions of partitions — single-digit-millisecond reads at any volume. Aurora Serverless v2 scales compute elastically and fans read-heavy cascade and search traffic to per-region replicas.
  • The live layer fans out instead of holding on. You can't hold a million database connections, so Cascade never tries: each event is published once — an Aurora trigger and a DynamoDB Stream — and fanned out through EventBridge to edge functions. Reaching a million screens happens at the edge, in parallel.

Global by the same design — DynamoDB Global Tables, Aurora read replicas, and Vercel's edge put data and compute beside every user, so a shock in Taipei hits London and São Paulo in the same second. And the workload itself is kind to scale: a cascade is one bounded query plus a rerank, so cost grows with events in the world, not people watching them.

Challenges we ran into

OIDC arrives as a header, not an environment variable. boto3 kept failing with "Unable to locate credentials" until we realized Vercel passes the identity token as x-vercel-oidc-token on each request. The fix — capture it into a context variable, exchange it through STS, and cache the result per role for thirteen minutes — became the backbone of every AWS call we make.

Scaling Aurora to zero means cold starts. min_capacity = 0 ACU saves real money, but the first request after a pause waits 10–15 seconds for the cluster to wake. We hide it behind a warmup ping in the SSE handshake so the user never stares at a blank globe.

Making the graph walk UI-ready. The front end expects a precise set of nodes and edges, each carrying a running impact score and the path it came from. Getting the recursive CTE to return exactly that — cumulative weight as a column, the originating ticker preserved per row, capped and ordered for the layout — took real schema work, not just a query.

Voyage's free tier is three requests a minute. We batch embeddings sixty-four to a call and fall back to text-only search when we're rate-limited, so results never stall waiting on the embedder.

Accomplishments that we're proud of

  • Zero static credentials. AWS access from Vercel is pure OIDC federation, end to end — no access key lives in the repo or the environment.
  • \$0 idle cost. Aurora scales to zero ACUs and DynamoDB bills on demand; the entire judging window costs us a few dollars.
  • A live channel that lives inside the database — Aurora LISTEN/NOTIFY straight through to the browser over SSE, with DynamoDB Streams as the second, AWS-native pillar.
  • A geo-cascade that can't hallucinate a symbol — every coordinate is range-checked and every ticker is verified against the real company list before it can reach the screen.
  • One query that does vector search, keyword search, a graph walk, and geography — exactly what the database choice was for.

What we learned

  • A recursive CTE turns a graph walk into something you can reason about in plain SQL: cumulative weight is a column, traversal depth is a WHERE clause.
  • DynamoDB Streams is change data capture you don't have to build — it turned live fanout from a feature into a setting.
  • OIDC through the Vercel Marketplace is the cleanest Vercel-to-AWS coupling we've used — the storage screenshot from the dashboard doubles as the architecture diagram.
  • Picking two databases on purpose, each for its strength, ended up simpler than forcing one engine to do both jobs.

What's next for Cascade

Two databases used deliberately — and a clear path to use far more of each.

Go deeper on Aurora.

  • Aurora Global Database — sub-second cross-region replication so the analytical plane is local to every market.
  • Read-replica auto-scaling — cascade and search are read-heavy; fan them across replicas as traffic climbs.
  • RDS Data API — connectionless HTTP access from serverless functions, so scaling out never hits a connection ceiling.
  • TimescaleDB + pg_partman — OHLCV price history and automatic event retention without a sweep job.

Go deeper on DynamoDB.

  • Global Tables — active-active, multi-region writes for true global low latency.
  • DAX — microsecond reads on hot tickers and watchlists.
  • A global secondary index — query the event mirror by ticker and sector, not just by source.
  • Export to S3 — stream the event lake to S3 to power backtesting, feeding realized price moves back into the cascade edge weights so the model sharpens with every event.

Push the intelligence further. Cross-asset contagion (FX, rates, commodities, crypto), multi-event interference when cascades collide on one ticker, a natural-language console — "what moves if TSMC halts for a week?" — and a public cascade API so any desk or newsroom can embed a live cascade.

Built With

Share this project:

Updates