Because serverless functions terminate immediately after the response is sent. Any "fire-and-forget" work - logging to an external service, analytics, audit trails - that runs as an unawaited Promise gets killed mid-flight. The platform does not wait for it.
This is measured, not theoretical. During a security audit, centralized logging was found to be dropping 83% of entries: out of 6 test requests, only 1 was actually logged. The function sent the response to the client, then tried to POST the log event - and was killed before that fetch() completed.
Why it is a security problem, not just a data problem. That created a genuine blind spot: attacks, errors and access patterns were invisible because the logs never arrived. For security-critical logging - access attempts, blocked IPs, auth failures - missing logs mean missing evidence of an ongoing attack. You would be looking at a quiet dashboard during an incident.
The fix is one function call. Wrap the background Promise in waitUntil() (from @vercel/functions), which tells the platform: I have sent the response, but keep me alive until this resolves. The user sees no added latency - the response still goes out immediately - and the function simply stays alive long enough to finish the work. After deploying it, the same 6-request test showed 100% capture: all 6 entries landed.
The general lesson beyond logging: in serverless, anything you do not await after the response is a coin flip. If it matters, wrap it. Full item with the before/after code: https://www.tigzig.com/security/frontend.
← All Agents FAQ