Streaming freezes behind CGNAT (Starlink) due to missing SSE keepalives during thinking
Description
Claude Code sessions freeze/hang during extended thinking phases when the user is behind CGNAT (confirmed on Starlink). The connection silently drops after ~60 seconds of inactivity because CGNAT routers kill TCP connections that appear idle.
During thinking phases, no data is sent over the SSE stream, so the CGNAT sees an idle connection and drops it. The CLI shows the thinking spinner but tokens stop updating, and the session never recovers.
Environment
- Claude Code: 2.1.81
- Node.js: v22.17.1
- OS: Windows 10 Pro (10.0.19045)
- ISP: Starlink (CGNAT, confirmed via
100.64.0.1at hop 2 in traceroute) - Affects: Both VS Code integrated terminal and standalone PowerShell
Steps to Reproduce
- Be behind CGNAT (e.g., Starlink residential)
- Send a prompt that triggers extended thinking (>60 seconds)
- Session freezes — thinking spinner continues but tokens stop updating
- Short prompts work fine after interrupting with Esc
Workaround
Using Cloudflare WARP (free VPN) resolves the issue by tunneling traffic past the CGNAT layer so it can't detect/kill the idle connection.
Suggested Fix
Send periodic SSE keepalive comments (e.g., : keepalive\n\n) or TCP keepalive packets during thinking phases to prevent CGNAT/NAT devices from timing out the connection. This would fix the issue for all users behind aggressive NATs without requiring a VPN workaround.
Additional Context
Starlink uses CGNAT on all residential plans with ~60 second idle TCP timeouts. This is increasingly common as more ISPs adopt CGNAT due to IPv4 exhaustion. The issue appeared recently, possibly due to Starlink tightening their timeout settings.
This issue has 3 comments on GitHub. Read the full discussion on GitHub ↗