Skip to content

vercel-flags-core: jitter ingest retries and batch-wait window, honor Retry-After#371

Open
vincent-derks wants to merge 1 commit intomainfrom
feat/jitter-ingest-retries
Open

vercel-flags-core: jitter ingest retries and batch-wait window, honor Retry-After#371
vincent-derks wants to merge 1 commit intomainfrom
feat/jitter-ingest-retries

Conversation

@vincent-derks
Copy link
Copy Markdown
Contributor

@vincent-derks vincent-derks commented Apr 30, 2026

Summary

The usage tracker's /v1/ingest retry path used a deterministic 100/200ms schedule with no jitter, and the 5s batch-wait window was likewise unjittered. Concurrent processes that started at the same moment would all flush together and, when the server returned a non-2xx, retry in lockstep — amplifyingtransient pressure. This PR addresses that and adds basic observability on dropped batches.

Changes

  • Full-jitter exponential backoff between retry attempts (AWS-style: delay = random(0, base * 2^(attempt-1)), capped at 5s). Replaces the previous attempt * 100 ms schedule.
  • Jittered batch-wait window: MAX_BATCH_WAIT_MS is now perturbed by ±20% per process so independent processes don't flush at the same wall-clock instant.
  • Honor Retry-After on non-2xx responses (delta-seconds and HTTP-date forms), capped at 5s so a misbehaving upstream can't keep the function alive.
  • Log exhausted flushes: when all 3 retry attempts fail, emit a structured warning so consumers can alert on dropped batches. Previously these were silent.

Test plan

  • 22 new unit tests in utils/backoff.test.ts covering parsing edge cases,
    exponential ceiling, Retry-After floor + cap, custom baseMs/capMs,
    and the symmetric jitter bounds.
  • 3 new integration tests in utils/usage-tracker.test.ts for end-to-end
    wiring (Retry-After flows into the retry loop, exhaustion log,
    no-exhaustion log on success).
  • Existing retry tests still pass unchanged.
  • pnpm --filter @vercel/flags-core test → 438/438 pass.
  • pnpm --filter @vercel/flags-core type-check → clean.

… Retry-After

Replace the deterministic 100/200ms retry schedule with full-jitter exponential
backoff, jitter MAX_BATCH_WAIT_MS by ±20% to desynchronize concurrent flushes,
honor Retry-After (capped at 5s), and log when a flush exhausts all retries.

Helpers extracted to utils/backoff.ts so they can be reused.
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented Apr 30, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
flags-playground Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
flags-sdk-dev Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
flags-sdk-next-15 Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
flags-sdk-next-16 Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
flags-sdk-snippets Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
flags-sdk-sveltekit-snippets Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
shirt-shop Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm
shirt-shop-api Ready Ready Preview, Comment, Open in v0 Apr 30, 2026 2:44pm

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant