CLAUDE LABJP
SUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, now two days awayLATEST — Version 2.1.231, released August 13, is current; it fixes MCP OAuth sign-in on servers that use a pre-registered clientRESUME — Version 2.1.229, released August 12, adds `claude remote-control --continue` for picking up your most recent Remote Control sessionSTREAM — SSE keepalive pings now prevent gateway streaming from dropping on idle timeout during long thinking pauses, which helps Vertex and Bedrock setupsSELFHOST — Version 2.1.224, released August 7, introduces the `claude self-hosted-runner` command for self-hosted environmentsMCP — Monthly MCP SDK downloads have passed 400M, a fourfold jump this year, with over 950 servers listed in the connectors directorySUNSET — The legacy Workbench and the experimental prompt tool APIs retire on August 17, now two days awayLATEST — Version 2.1.231, released August 13, is current; it fixes MCP OAuth sign-in on servers that use a pre-registered clientRESUME — Version 2.1.229, released August 12, adds `claude remote-control --continue` for picking up your most recent Remote Control sessionSTREAM — SSE keepalive pings now prevent gateway streaming from dropping on idle timeout during long thinking pauses, which helps Vertex and Bedrock setupsSELFHOST — Version 2.1.224, released August 7, introduces the `claude self-hosted-runner` command for self-hosted environmentsMCP — Monthly MCP SDK downloads have passed 400M, a fourfold jump this year, with over 950 servers listed in the connectors directory
Articles/API & SDK
API & SDK/2026-08-15Intermediate

The Connection That Dies Mid-Thought Is Being Killed by Your Relay, Not the Upstream

Put a proxy or Worker in front of Claude Code and long thinking pauses start dying. The cause is neither the model nor the upstream — it is your relay holding the byte stream. Six relay behaviors compared side by side, plus how to verify yours before it ships.

Claude Code218SSE5streaming22gateway2proxyCloudflare Workers15timeout10

Premium Article

Short prompts sail through every time. The ones that make the model think die partway, and the upstream logs show nothing at all.

If you have a relay of your own sitting in the request path, you may have met this shape of failure. I did, shortly after writing a small relay that runs at the edge. My first suspicion was instability on the model side. That was wrong. The thing cutting the connection was the handful of lines I had written myself.

What makes it awkward is that the fault only shows up on heavy work. Smoke tests use short prompts, so everything passes, and the first real failure arrives on the day someone asks for something hard.

The conclusion, up front

The disconnect is not triggered by a failed response. It is triggered by no bytes arriving for a while.

For connections through ANTHROPIC_BASE_URL or ANTHROPIC_AWS_BASE_URL, Claude Code counts every byte your gateway relays. SSE ping events and comment lines all count, and a stream that goes completely silent for 300 seconds is aborted by default. This is written into the official gateway protocol reference.

During a long thinking pause, the upstream's keep-alive pings are the only traffic on the wire. So the moment your relay drops them, or holds them to flush later in a batch, the line goes silent as far as the client is concerned — while the upstream is still talking perfectly happily.

Version 2.1.229, released on August 12, 2026, added SSE keepalive pings to gateway streaming responses during long thinking pauses, which addressed idle-timeout disconnects on Vertex and Bedrock upstreams. The same release fixed a case where the idle timeout fired on custom ANTHROPIC_BASE_URL gateways even though keep-alive pings were demonstrably arriving on the wire. The upstream side has been improved. What remains is the relay you wrote.

The watchdog counts bytes, not meaning

This is where I first went wrong. I had assumed the client was checking whether it had received a ping event. It is far more primitive than that: it only looks at how many bytes arrived.

That primitiveness cuts both ways. Anything at all flowing resets the clock, even if it is not shaped like a ping. And a perfectly correct ping resets nothing if your relay is holding it.

Worse, the monitoring mechanism itself swaps out depending on which environment variable you connect with. Confuse these and you will harden a path that was never the one failing.

Variable used to connectMonitoring mechanismDefault on silence
ANTHROPIC_BASE_URL / ANTHROPIC_AWS_BASE_URLByte-level watchdog (comment lines count)Abort after 300 seconds
ANTHROPIC_BEDROCK_BASE_URLNot wrapped by the watchdog. Can be added with CLAUDE_ENABLE_BYTE_WATCHDOG_BEDROCK5-minute idle timeout
ANTHROPIC_VERTEX_BASE_URL / ANTHROPIC_FOUNDRY_BASE_URLNot wrapped by the watchdog5-minute idle timeout

The trap here is that a gateway can speak the Anthropic Messages format while the client connects through ANTHROPIC_BEDROCK_BASE_URL, in which case the byte-level watchdog does not wrap it. "Same format, therefore same behavior" does not hold. When someone brings me a disconnect, the first thing I ask is not the model name or the region — it is which variable you are connecting with.

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
You will be able to tell whether a mid-thought disconnect came from the upstream, the relay, or the client without adding a single new log line
You will be able to check whether your own proxy or Worker is hoarding the stream before it reaches production instead of after
You will be able to tell which connection paths the 300-second byte watchdog actually guards, because the environment variable you connect with changes the mechanism entirely
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

Claude 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-07-04
Reading the Claude apps gateway Announcement, I Rebuilt My Indie-Scale Control Plane
The self-hosted Claude apps gateway is a control-plane/data-plane separation you can scale down. Per-app cost attribution, model allowlists, and fail-closed spend caps, implemented as a small Cloudflare Workers proxy.
API & SDK2026-04-26
Claude API Streaming Stops Mid-Response: Diagnosing and Fixing the 5 Root Causes
When Claude API streaming stops unexpectedly, there are exactly 5 root causes. Learn to diagnose which one you're hitting and apply the right fix — from timeout tuning to stop_reason logging.
API & SDK2026-04-13
Implementing Claude API SSE Streaming in Next.js App Router
Learn how to implement Server-Sent Events streaming from the Claude API in Next.js App Router. Covers ReadableStream, React hooks, cancellation, and error handling with production-ready code.
📚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 →