For Synthriderz operators
How Newman uses your public API
Newman is an unofficial fan tool. It reads public Synthriderz JSON only — no scraping HTML, no accounts, no write endpoints. This page is the load + mitigation statement we want you to be able to point at before anything goes broadly live.
What we call
GET /api/leaderboards/profile/{user}— profile stats (once per player, cached)GET /api/scores?…&pb=1&limit=100&page=N— personal bests with embedded leaderboard metadata (paginated)GET /api/leaderboard-profiles?s=…— player autocomplete / existence checks (short queries, limit ≤ 20)GET /api/leaderboards/{id}— occasional beatmap-id resolve for leaderboard deep links (lazy, not on the ingest hot path)
User-Agent: newman-sr/1.0 (+https://github.com/heavygee/newman.rip)
Load we put on Synthriderz
- A cold pull for a heavy player is on the order of tens of score pages (100 PBs per page). Two players ≈ two of those crawls.
- Autocomplete hits leaderboard-profiles while someone types (debounced ~ 250ms on the client; still subject to our server rate gate).
- Manual refresh is allowed, but cooldown-gated per player (default 15 minutes).
How we mitigate
| Rule | What we do |
|---|---|
| No parallel upstream fan-out | One global fetch queue. At most one Synthriderz-touching job runs at a time (Postgres claim + SKIP LOCKED). |
| ≥200ms between calls | Server-side rate limiter (SYNTHRIDERZ_MIN_DELAY_MS, default 200). Sequential pages only. |
| Cache first | PBs cached in Supabase (default 24h). Profiles cached (default 6h). Repeat visits serve from cache — zero upstream if warm. |
| Stale-while-revalidate | If we already have PBs, we show the last report immediately while a refresh drains in the background — so users stop hammering refresh. |
| Incremental jobs | Score pulls are paginated job ticks (usually 1 page per tick). Vercel functions never try to download an entire catalog in one request. |
| Short cron drains | Queue kicks budget ~45s on Hobby so we return cleanly; a host timer retries every 2 minutes instead of one long scrape. |
| No beatmap resolve on ingest | Score pages upsert without resolving every leaderboard→beatmap id up front (that used to multiply API calls per page). |
| Player validation | Home autocomplete only starts a rivalry for names that exist in leaderboard-profiles — fewer accidental crawls of typos. Uses Synthriderz nestjsx-crud $startsL / $contL / $eqL. |
| Honest identity | Identifiable User-Agent pointing at the GitHub repo. No browser impersonation. |
What we do not do
- No login, cookies, or session hijacking
- No POST/PUT/DELETE against Synthriderz
- No HTML scraping of the site
- No selling data; private fan app (not a commercial product)
- No LLM rewriting of scores — compare math is deterministic over cached rows
Contact
If Synthriderz operators want a lower rate, a allowlist, or for Newman to stop: open an issue on github.com/heavygee/newman.rip or message the maintainer (HeavyGee / Gavin). We will honor a clear request to throttle or shut off.
Live app: newmanrip.vercel.app. This page: /respect.