◉GEMINI LABJP
●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…●ARGON — gemini-4-argon is generally available as of 10/13, aimed at complex coding, agents, math and science●DEEP RES — deep-research-pro-preview-12-2025 shuts down 10/23, 6 days left. Move to deep-research-preview-04-2026●NANO — gemini-nano-banana-2.1 is GA (10/06). gemini-3.1-flash-image is deprecated with no shutdown date yet●MCP — One write-up cut an 85,000-token tool result to 310 tokens by wrapping it in an ADK FunctionTool●FLASH — gemini-3.7-flash and 3.5-flash now route automatically to newer Flash models (10/08)●NEW — Stop Re-Reading Every Crash Report: Gre…
Articles/API / SDK
◈ API / SDK/2026-04-29Advanced

Production Streaming UI with Gemini API + TanStack Query — Cancellation, Retries, and Cache Coherence

TanStack Query is optimized for one-shot REST/JSON requests, so streaming responses don't fit naturally. This guide walks through the gotchas of using Gemini API SSE with TanStack Query and the production-grade design patterns that hold up in real apps.

Gemini API249TanStack QueryReactStreaming5Production33

✦ Premium Article

Production Streaming UI with Gemini API + TanStack Query — Cancellation, Retries, and Cache Coherence

Have you ever started writing an AI chat with useMutation thinking "TanStack Query is great, I'll just use it for state too," and then hit a wall the moment streaming kicked in? I did. Showing partial chunks on the screen was easy enough, but then I tripped over every production landmine in turn: duplicate streams when users hammered the send button, retry storms after tab focus, half-rendered text after errors.

TanStack Query is optimized for the "send a request, get JSON back" model. Streaming responses (SSE or ReadableStream) live outside that model, and naive integration falls apart. This article shares the patterns I converged on while shipping Gemini-powered chat UIs to production — with copy-pasteable code.

Why TanStack Query and Streaming Don't Mix Naturally

TanStack Query handles caching, deduplication, and refetching for a given key. Its mental model assumes "one request, one response." Streaming is fundamentally different: chunks arrive over time, the stream might be cancelled, and the final result is the concatenation of chunks rather than the last one.

If you ignore this difference and try to fit streaming into useQuery, you'll watch select re-render the whole tree every chunk, and staleTime semantics will collapse. The conclusion I arrived at: handle the stream itself with useMutation, and only sync the finalized result into the query cache via queryClient.setQueryData.

Conceptually:

  • User submits → mutate() is called
  • Inside mutationFn, consume the ReadableStream chunk by chunk
  • Push partial text into local React state for live display
  • On completion, call queryClient.setQueryData(['conversation', id], full)
  • Other components read history through useQuery

With this split, you keep TanStack Query's strengths (caching, invalidation, optimistic updates) while letting plain React state handle the streaming-specific concerns.

✦

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
✦Anyone stuck wiring useMutation to a ReadableStream will leave today with a complete, working implementation that handles cancellation, retries, and partial-result preservation
✦You'll learn how to control the duplicate streams and memory leaks that appear when users switch tabs and refocus mid-stream, by combining queryClient with AbortController correctly
✦Even when users hammer the send button or connections drop, your UI will stay intact, partial replies will be preserved, and your server-side token spend will drop noticeably
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

◈ API / SDK2026-08-23
Streaming Gemini TTS: concatenate the PCM, write the WAV header once
Streamed Gemini TTS does not arrive as an audio file. It arrives as raw PCM fragments. Here is what happens when you wrap each fragment in its own WAV header, measured on my machine, plus the receiving code that avoids it.
◈ API / SDK2026-08-07
When Streaming Responses Quietly Lose Non-ASCII Text: Measuring the Byte Boundary and the Event Boundary Separately
I measured why Japanese text disappears from streaming Gemini responses using a local mock SSE server. Two separate layers were broken, one of them silently, and an English-only test suite caught neither.
◈ API / SDK2026-05-21
Designing Event-Driven AI Workflows with Gemini API and Cloud Pub/Sub — Notes from an Indie Developer
An implementation memo on wiring Gemini API into Cloud Pub/Sub event-driven workflows. Using an app-review analysis pipeline as the running example, the article covers retry policy, dead-lettering, idempotency, and cost guardrails — from the perspective of someone running it solo.