tRPC Request Header Logging
How BlueClerk logs X-Fetch-Snapshot headers for debugging Next.js caching issues
Overview
BlueClerk's tRPC server automatically logs the X-Fetch-Snapshot header from incoming requests to help diagnose Next.js partial prerendering (PPR) and fetch caching behavior. This header indicates whether a request is being served from Next.js's snapshot cache versus a dynamic fetch, making it easier to debug stale data issues and unexpected caching behavior.
What Gets Logged
X-Fetch-Snapshot Header
When a tRPC request includes this header:
- Header value - Typically "1" when serving from snapshot cache
- Request context - Which tRPC procedure was called
- Logged to console - Appears in Vercel runtime logs for debugging
Why This Matters
Debugging Cache Behavior
The X-Fetch-Snapshot header helps identify:
- Stale data issues - When cached snapshots serve outdated content
- PPR behavior - How Next.js decides what to prerender vs. fetch dynamically
- Cache invalidation problems - When revalidation isn't working as expected
- Unexpected static serving - Routes that should be dynamic but aren't
How to Use This Information
Finding Logs
- Open Vercel runtime logs for your deployment
- Search for
X-Fetch-Snapshotin the logs - Look for patterns - Which procedures trigger snapshot serving?
- Correlate with user reports - Do stale data complaints match snapshot logs?
Common Patterns
- Header present - Request served from prerendered snapshot
- Header absent - Request executed dynamically
- Frequent snapshot hits - May indicate overly aggressive caching
Questions
Q: Does this log every request?
A: No - only requests that include the X-Fetch-Snapshot header are logged. Most dynamic requests won't include this header.
Q: Can I disable this logging? A: This is debug-level logging intended for production troubleshooting. It's lightweight and doesn't impact performance, so it's always enabled.
Q: What should I do if I see unexpected snapshot serving?
A: Check your Next.js caching configuration, revalidation settings, and consider adding fetchCache: "force-no-store" to routes that should always be dynamic.