connected realms in the US, Europe, Korea, and Taiwan
2.69B
retail price rows, compressed 16.5×
9.8 s → 0.64 s
cold item-page load
66,000+
tests in the CI suite
What I built
I build and operate the path from upstream auction data to the page a
player uses to decide what to buy or sell: collection, storage, APIs,
caching, the web app, a Tauri desktop companion for Windows, and the
in-game addon it installs. The platform runs as 17 services on Railway.
Engineering decisions
Upstream validation
An upstream schema break must not look like an empty auction house. The
collector distinguishes missing or malformed auction data from a valid
empty result, preserving the difference between “nothing is listed” and
“we could not read the market.”
Cache behavior
A popular query can arrive many times while the cache is cold. The Redis
layer coalesces misses, validates selected cached shapes with Zod, and
uses bounded failure paths. Cache behavior is part of the API contract,
not just a speed optimization.
Three data sources
Blizzard’s API covers retail across 184 connected realms in four
regions, the TSM API covers the classic editions, and for WoW Forever
the desktop companion uploads players’ own auction scans. Each edition
has its own TimescaleDB instance, and collection follows each source’s
cadence rather than pretending every market updates continuously.
Latency under load
Time-boxing server-side prefetch cut cold item pages from 9.8 s to
0.64 s. In September 2026 I traced a spike of 503 errors to an index
that blocked PostgreSQL’s in-place updates and a rollup that stalled
Node’s event loop for up to 16 seconds. After the fix, a 600-request
sample showed p99 latency down from 36.9 s to 2.6 s and 503s from 22
to 0.
Tests that match the change
More than 66,000 tests run in CI, but most changes touch a small part
of the code. In a replay of 110 failed CI runs, predictive test
selection ran a median 13.7% of the test files and still caught 94 of
the 110 failing test files.
How it works.
Architecture
One API serves the web app, the desktop companion, and the in-game addon.
SourcesBlizzard, TSM, player scans
CollectorsSource-aware schedules
HistoryTimescaleDB per edition
API & cacheExpress and Redis
Clients
Web app
Desktop companion
In-game addon
The tradeoff
Freshness, cost, and responsiveness pull in different directions. I use
source-aware collection and layered caches so the user can get a useful
answer without every request repeating the same upstream work.