Summary
A custom intermediate URL in front of the Add to Google Wallet save URL is technically feasible, but it introduces a failure mode that often goes unnoticed: the redirect chain breaks the expected contract of the Google Wallet button. This postmortem explains how such designs fail in production, why they fail, and how senior engineers prevent these issues.
Root Cause
The core issue is that the Google Wallet button is designed to link directly to a signed save URL, but the system was modified to route the user through a custom server endpoint first. This introduces:
- Additional network hops that can fail or time out
- JWT generation delays under load
- Redirect logic that may not preserve required parameters
- Unexpected caching or CDN behavior on the custom domain
- Browser or app blockers interfering with redirects
The result: users click the button, but the pass never reaches Google Wallet.
Why This Happens in Real Systems
Real production systems experience:
- Latency spikes that cause the intermediate endpoint to exceed redirect timeouts
- Race conditions in on-demand JWT generation
- Misconfigured load balancers that strip query parameters
- Security middleware that blocks or rewrites redirect URLs
- Mobile app WebViews that behave differently from desktop browsers
Even if the flow works in development, these real-world variables cause intermittent failures.
Real-World Impact
Teams typically see:
- Lower pass-add rates because some users never reach the Google Wallet save URL
- Inconsistent behavior across devices
- Hard-to-debug failures because the redirect hides the root cause
- Increased support tickets when users report that “the button doesn’t work”
- Analytics distortion because redirects fail silently
Example or Code (if necessary and relevant)
Below is a minimal example of a redirect endpoint that often becomes the bottleneck:
app.get("/digital/pass", async (req, res) => {
const token = req.query.token;
const user = await validateUser(token);
if (!user) return res.status(403).send("Invalid user");
const saveUrl = await generateGoogleWalletSaveUrl(user);
return res.redirect(saveUrl);
});
How Senior Engineers Fix It
Experienced engineers avoid fragile redirect chains and instead:
- Pre-generate JWTs when possible, caching them for short periods
- Use signed, expiring URLs directly in the button
- Move validation earlier in the flow, not at the moment of clicking the button
- Ensure the button always points directly to pay.google.com
- Use server-side event logging instead of redirect-based analytics
- Implement background workers to generate passes asynchronously
The guiding principle: the Add to Google Wallet button must be deterministic and must not depend on runtime server logic.
Why Juniors Miss It
Less experienced engineers often:
- Assume redirect chains are harmless, not realizing how brittle they are
- Underestimate mobile WebView quirks
- Treat JWT generation as a synchronous, low-risk operation
- Focus on “what works locally” instead of “what survives production traffic”
- Use the button as a trigger for business logic, rather than a final step
They see the redirect as a convenient place to insert validation, but senior engineers know that the button click must never be a point of failure.