fix(analytics): wrap GA4 fetch in waitUntil to prevent dropped events#59
Merged
Woody4618 merged 1 commit intoMay 25, 2026
Merged
Conversation
The fire-and-forget fetch() in trackEvent() returns a dangling Promise that the Vercel serverless runtime cancels the moment the response is returned. With GA4_MEASUREMENT_ID and GA4_API_SECRET correctly set in production, events were still never reaching google-analytics.com because the POST was cut off mid-flight. Wrap the fetch in waitUntil() from @vercel/functions so the runtime keeps the function instance alive until the GA4 request settles — without blocking the airdrop response. waitUntil is runtime-agnostic and reads a context object Vercel injects on globalThis; it does not change the deploy type, the runtime (Node.js Fluid Compute), regions, or pricing. Outside Vercel it silently no-ops, matching the prior fire-and-forget semantics.
|
@askov is attempting to deploy a commit to the Solana Foundation Team on Vercel. A member of the Team first needs to authorize it. |
4 tasks
Woody4618
approved these changes
May 25, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
The fire-and-forget
fetch()intrackEvent()(lib/analytics.ts) returns a dangling Promise that the Vercel serverless runtime cancels the moment the response is returned. WithGA4_MEASUREMENT_ID/GA4_API_SECRETcorrectly set in production, events were still never reachinggoogle-analytics.combecause the POST was cut off mid-flight — silently, since GA4's/mp/collectreturns 204 regardless of whether anything was actually sent.This was introduced together with the analytics module in #57.
Fix
Wrap the fetch in
waitUntil()from@vercel/functionsso the runtime keeps the function instance alive until the GA4 request settles — without blocking the airdrop response.Why
waitUntiland notawait?awaitis also a valid fix — the cost is ~50–100 ms added to a request that's already 1–3 seconds (Turnstile + Solana RPC + backend logging). The choice forwaitUntilhere is to preserve the doc-stated contract thattrackEvent"never blocks the airdrop response," and to isolate the airdrop path from any GA4 outage / TLS hang.waitUntilis runtime-agnostic and reads a context object Vercel injects onglobalThis. It does not change the deploy type, the runtime (Node.js Fluid Compute), regions, or pricing. Outside Vercel (self-hosted) it silently no-ops, matching the prior fire-and-forget semantics.Test plan
npx vitest run— all 111 tests pass locally (no test changes required; existing tracking tests mock@/lib/analytics)GA4_MEASUREMENT_ID+GA4_API_SECRETsetairdrop_successappears in GA4 Realtime within ~30 secairdrop_failedwithreasonparam appears/debug/mp/collectonce to validate payload shape (GA4 silently drops invalid events on the prod endpoint)