01
Rate limits made the product look dead
A big run fanned out every engine call at once. It hit the provider's per-minute ceiling, and each 429 was saved as a permanent engine error with no result. The dashboard hides empty results, so for affected accounts the whole product looked broken.
FixEvery engine call goes through one wrapper that retries 429, 529 and 5xx with exponential backoff, honors Retry-After, and spreads retries with deterministic jitter. A concurrency cap keeps calls under the per-minute limit instead of bursting past it.
02
One hung connection could kill the weekly run
There was no timeout anywhere. A provider that opened a socket and never answered held the request open, and edge functions die at about 150 seconds, so one silent engine took down the run for every business after it.
FixTwo bounds, because one is not enough: a ceiling per attempt and a total budget per call that fits inside the function's lifetime, both wired through AbortSignal so a caller can still cancel.
// the shape of it
const MAX_RETRIES = 4
const PER_ATTEMPT_TIMEOUT_MS = 45_000
const TOTAL_BUDGET_MS = 110_000 // under the ~150s isolate limit
export async function fetchWithRetry(url, init, opts = {}) {
const deadline = Date.now() + (opts.totalBudgetMs ?? TOTAL_BUDGET_MS)
for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
// per-attempt AbortSignal, backoff, Retry-After, deadline check
}
}
03
AI answers are untrusted input
The parser reads text written by other models and descriptions written by customers. Either one could tell it what to conclude, or blow up its cost.
FixCustomer fields are flattened so they can't forge prompt structure, and labeled as data rather than instructions. Answers are capped before parsing so one bad response can't cost a hundred times the original call, and citation lists are bounded. The prompt stays byte-identical when nothing changes, so prompt caching keeps working.
04
Letting Claude use SeenRank directly
A Claude user should be able to ask "how am I doing?" and get their real SeenRank numbers, without copying anything over.
FixA hosted Model Context Protocol server with its own OAuth 2.1 authorization server: discovery metadata, dynamic client registration, PKCE, short-lived audience-bound tokens stored hashed. The user signs in to SeenRank and consents, and Claude never sees their session. The MCP tools and the REST API share one implementation, so they can't drift apart.
05
An agent that acts, carefully
Iris, the in-app assistant, has 11 tools. Reading data is free. Writing data, like adding a business or a question, means confirming the specifics in one sentence and then acting in the same turn, so it is fast without being reckless.
FixTools only ever touch the signed-in user's own account through row-level security, paid features are gated server-side by subscription status, and every tool result is reported back in plain words.