GEMINI LABJP
NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20NANOLITE — Nano Banana 2 Lite is here: Google's fastest and most cost-efficient Gemini Image model, made for running lightweight image generation cheaplyOMNIFLASH — Gemini Omni Flash is in public preview, a natively multimodal model that lets enterprises and developers build custom, dynamic video workflowsAGENTS — Managed Agents expand with background: true for async server-side runs and polling, remote MCP server integration, and refreshing credentials across interactionsMEMORY — The Memory Bank IngestEvents API is generally available, decoupling event ingestion from memory generation so you can stream content continuouslyTHROUGHPUT — Provisioned Throughput now lets you submit up to seven pending orders for the same model and regionDEPRECATE — Image generation models shut down on August 17, and the Grok 4.1 family on the Gemini Enterprise Agent Platform on August 20
Articles/Dev Tools
Dev Tools/2026-05-28Advanced

Replaying Gemini API Calls Locally with msw and HTTP Fixtures — How I Cut API Quota Across Six Sites with a Record/Replay Pattern

When you hit the real Gemini API every time you tweak a piece of UI, you end up paying for hundreds of duplicate calls a day. After moving six of my sites to an msw-based record/replay pattern, monthly Gemini billing went unexpectedly quiet. Here's the implementation and operating policy.

mswlocal developmentAPI quotaTypeScript8indie developer12streaming28

Premium Article

The coffee had gone cold and I was still fiddling with a loading indicator when I happened to open the Gemini API usage dashboard. The same prompt had been fired eighty times that morning. I just wanted to see how the new bounce felt; my finger had been doing the rest. I'm Masaki Hirokawa, an artist and indie developer running four sites under Dolice Labs plus two more under a separate brand — six in total — and over the last few weeks I've spent serious time figuring out how to stop the "unconscious billing" that creeps into a Gemini-powered codebase.

Hitting the real API every time you tweak a piece of UI looks innocent in a code review. But once you watch the same pattern across six sites for a couple of months, you start noticing that UI iteration and evaluation share the same client, and a workflow that should need ten honest calls per day ends up making well over a hundred because UI tinkering is hidden inside the same fetch path. Rebuilding it so msw sits at the fetch layer and replays HTTP fixtures looked the same from the outside, but my API usage went quiet — and as a side effect, streaming UI bugs became much easier to find.

These notes walk through the four axes I ended up caring about: spinning the local loop quickly, recording fixtures correctly, replaying them in a way that still surfaces real-world bugs, and refusing to conflate UI fixtures with evaluation fixtures.

What actually breaks when you hit the real API for UI work

It helps to be precise about what's breaking, because on the surface nothing is. Three layers rot quietly when you let the real Gemini API drive every UI iteration.

The first is iteration speed. In the admin panel of my wallpaper app, generateContent averages 1.4 seconds, and a streaming response completes in about 3.2 seconds. Waiting three seconds every time I nudge a 4px margin breaks the design flow noticeably.

The second is quota and billing. Since 2014 I've been routing some of the AdMob revenue from a catalog that has now passed 50 million cumulative downloads into infrastructure for the Lab sites. Watching that money leak into duplicate API calls is the kind of friction I prefer to remove. Gemini 2.5 Flash is cheap on its own, but six sites running an admin panel each turn "just checking the layout" into a few thousand yen a month.

The third — and the most insidious — is that UI test coverage drops. A real streaming endpoint returns slightly different lengths each time. I want to deliberately exercise the loading state, the typewriter render, mid-stream cancellation, and error paths, but with the real API everything "kind of works most of the time," and the edge cases drift out of sight.

I spent about two months trying things to solve all three at once. The answer is just "intercept fetch and return canned responses," but the entire game is in how you make, store, and retire those canned responses.

Why I settled on msw — works in both the Service Worker and Node

I considered nock (old), undici interceptor (ESM headaches), miragejs (overbuilt with an ORM layer), and hand-rolled fetch wrappers (invasive). I ended up standardising on msw across all six sites.

Three reasons. First, msw runs as a Service Worker in the browser and as a native fetch interceptor in Node, which lets the Next.js client and server share the same handlers. Second, I don't have to change a single line of production code to install it, which matters when I'm trying to roll the same setup into six separate repos. Third, streaming responses (SSE) are just "return a ReadableStream," so I can emulate Gemini's streamGenerateContent without contortions.

One important caveat: msw needs public/mockServiceWorker.js to be present, and Service Workers do not run inside wrangler dev. I keep wrangler-dev verification on the real API and only put local UI iteration on msw.

Thank you for reading this far.

Continue Reading

What follows includes implementation code, benchmarks, and practical content we hope you'll find useful. This site runs without ads — server and development costs are supported entirely by members like you. If it's been helpful, we'd be truly grateful for your support.

WHAT YOU'LL LEARN
A concrete implementation that uses msw at the fetch layer to replay Gemini generateContent and SSE responses from fixtures
A record/replay design that cut my combined Gemini calls from about 1,200 per day across six sites down to roughly 80
An operating policy that separates UI fixtures from evaluation fixtures, with a refresh procedure for model upgrades
Secure payment via Stripe · Cancel anytime

Unlock This Article

Get full access to the rest of this article. Buy once, read anytime. This site is ad-free — your support goes directly toward keeping it running.

or
Unlock all articles with Membership →
Share

Thank You for Reading

Gemini Lab is ad-free, supported entirely by members like you. We publish practical guides daily with implementation code, benchmarks, and production-ready patterns. If you've found it useful, we'd love to have you on board.

  • Copy-paste ready implementation code
  • New advanced guides published daily
  • $5/mo or $10 for lifetime access
View Membership →

Related Articles

Dev Tools2026-07-09
Closing the Failures That Never Throw: Normalizing Gemini API Responses into a Discriminated Union
An HTTP 200 with an empty body will never reach your catch block. Here is how I normalize finishReason and blockReason into a discriminated union, and let a never check turn missed cases into compile errors.
Dev Tools2026-07-03
Stop Making Listeners Wait for the Whole File — Wiring Gemini TTS Streaming into Your Delivery Path
gemini-3.1-flash-tts-preview now streams audio via streamGenerateContent. A delivery path with 1.8s to first sound, covering PCM boundary handling, sentence-level resume, and a fallback for preview shutdown.
Dev Tools2026-06-20
Routing Gemini by Pipeline Stage: Draft on Flash, Finish on the Top Tier
A record of reworking which Gemini model handles which stage of an automation pipeline, prompted by the general availability of Gemini 3.5 Flash and the rollout of 3.1 Flash-Lite. Includes a small router that splits work into draft, classify, and finalize stages, how the cost picture changes, and the guardrails I settled on.
📚RECOMMENDED BOOKS
Build a Large Language Model (From Scratch)
Sebastian Raschka
LLM Dev
Prompt Engineering for LLMs
Berryman & Ziegler
Prompting
AI Engineering
Chip Huyen
AI Eng
* Contains affiliate links
See all →