Earn Aggregator
I was looking for the best stablecoin yield across exchanges and found myself checking Binance, Bybit, Bitget, MEXC, and Gate.io manually every time. APYs change daily, sometimes hourly. I was spending ten minutes on a task that should take ten seconds, and there was no API that gave me all five in one call. So I built one.
The architecture is straightforward: Fastify + TypeScript on Vercel Serverless Functions, with Upstash Redis for caching at a 7-day TTL. A Vercel Cron job runs every 6 hours to refresh the cache proactively. On a cache miss, the API can optionally trigger a live refresh from the exchanges. Rate limiting via @fastify/rate-limit keeps it from being abused. The whole thing runs on Vercel's free tier for effectively zero cost.
The interesting engineering problem was normalization. Each exchange has a completely different API structure: different authentication models, different response shapes, different field names for the same concept. Binance returns earn products in a flat list; Gate.io nests them inside product categories. Building a per-exchange adapter layer that outputs a consistent { exchange, asset, apy, type } shape took careful design. Gate.io's API was the most divergent and needed the most special-casing.
The 7-day TTL on the cache was a deliberate choice. Earn APYs don't change fast enough to need sub-hour freshness for most use cases, and the long TTL means the API stays functional even if the cron fails several times in a row. In production, the cache hit rate is high enough that exchange APIs rarely get called directly at all — most requests are served entirely from Redis.