◉CLAUDE LABJP
●2.1.283 — No Claude Code release over the weekend; 2.1.283 from September 25 is still the latest. Its new auto-mode default deserves a check against your allow rules●PLANS — Pro and Team Standard now default to Opus instead of Sonnet, a change shipped in Claude Code 2.1.280 that shifts how you compare plans●10/07 — Nine days left until the old spellings of the Claude Desktop / Cowork managed config keys stop being accepted; after that they fail closed●AUTO — Users are asking why commands covered by allow rules get rejected in auto mode. The fix is shaping the invoked command to match the rule●NEW — The week Opus 5.5 became the default: three places an alias was still pointing at the old model●CURSOR — Cursor credits burn in proportion to model cost, so routing Claude through Cursor gets expensive fast. Above ~50 requests a day, flat-rate Claude Code Pro is the steadier choice●2.1.283 — No Claude Code release over the weekend; 2.1.283 from September 25 is still the latest. Its new auto-mode default deserves a check against your allow rules●PLANS — Pro and Team Standard now default to Opus instead of Sonnet, a change shipped in Claude Code 2.1.280 that shifts how you compare plans●10/07 — Nine days left until the old spellings of the Claude Desktop / Cowork managed config keys stop being accepted; after that they fail closed●AUTO — Users are asking why commands covered by allow rules get rejected in auto mode. The fix is shaping the invoked command to match the rule●NEW — The week Opus 5.5 became the default: three places an alias was still pointing at the old model●CURSOR — Cursor credits burn in proportion to model cost, so routing Claude through Cursor gets expensive fast. Above ~50 requests a day, flat-rate Claude Code Pro is the steadier choice
Articles/Claude Code
⟐ Claude Code/2026-06-28Advanced

When You Fan Out Streaming Sessions, Your Laptop's CPU Gives Out First — An Adaptive Throttle That Caps Concurrency by Measured Load

Even with lighter streaming, fanning out many sessions on one machine saturates the host CPU before anything else. Here is why a fixed semaphore fails, plus a working adaptive gate that raises and lowers concurrency from measured CPU.

Claude Code257Concurrency3Streaming4Performance4Unattended Automation3

✦ Premium Article

A recent Claude Code update cut CPU usage during streaming by roughly 37%. For anything that runs for hours, that is a welcome lift. But running several sites' publishing jobs in parallel on a single machine, I keep noticing that this kind of improvement reduces the per-session cost — it does nothing about the separate question of what gives out first when you stack many sessions at once.

On my own setup, the moment I ran each site's generation concurrently, the fan started spinning and a latency I had never seen with serial runs showed up at p95. Memory was nowhere near full. This article rebuilds that bottleneck — when the limiting resource turns out to be host CPU — by replacing a guessed, fixed concurrency number with a gate that throttles based on measured CPU, using working code and numbers from my own runs.

Why CPU Gives Out Before Memory

A streaming response is a steady loop of receiving server-sent events one at a time, parsing incremental JSON, and stitching text together. For one session this is trivial. Run the same loop across ten or twenty sessions, and the event loop sees a relentless pile of small parse-and-callback work, and CPU becomes the limiting factor.

What matters here is that each session is a busy coroutine, not a mostly-sleeping one. When the time spent handling arriving chunks outweighs the time spent waiting on the network, the usual I/O-concurrency intuition ("lots of waiting, so stack many") breaks down. Memory grows roughly linearly with session count and is easy to predict, while CPU hits a cliff once it saturates. That is exactly why you need a layer that decides concurrency by watching CPU, separate from any memory watchdog.

Stop Guessing "How Many at Once"

Most batch jobs cap concurrency with a fixed semaphore like this:

import asyncio
 
# A guessed constant. Comfortable on the dev machine, but...
sem = asyncio.Semaphore(12)
 
async def run_one(site, client):
    async with sem:
        async with client.messages.stream(
            model="claude-sonnet-4-6",
            max_tokens=4096,
            messages=[{"role": "user", "content": build_prompt(site)}],
        ) as stream:
            async for _ in stream.text_stream:
                pass
        return await stream.get_final_message()

The trouble is that 12 is optimized for one specific machine at one specific moment. On the faster Mac I develop on, twelve sessions were fine. The instant I moved the same script to a scheduled run on an older mini PC, CPU pinned at around 96% and each stream took about 2.4x longer than it did alone. On a large, otherwise-idle machine, twelve underutilizes it. A constant fits neither the fast side nor the slow side.

✦

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
✦Why a fixed semaphore is silently tuned for your fastest machine and saturates the CPU on a weaker host
✦A working adaptive gate that samples host CPU with an EWMA and adjusts the concurrency limit one slot at a time
✦Backpressure that pauses new work while guaranteeing at least one in-flight session, and how to share one script across machines
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 $15 for lifetime access
View Membership →

Related Articles

⟐ Claude Code2026-09-04
The ~/.claude.json Rollback Is Fixed in v2.1.259. Putting Back What It Erased Is Still Your Job
Concurrent sessions used to silently roll back each other's ~/.claude.json changes. v2.1.259 fixed that, but nothing restores the trust settings and MCP servers you already lost. Here is how I find and rebuild them, with a small key-path diff script.
⟐ Claude Code2026-08-06
The Skill Call That Returned Nothing — Pinning Down Name Resolution Before an Unattended Run
A skill whose name collides with a built-in terminal command may never resolve in a non-interactive session. Here is a preflight that builds the effective-name table before launch, plus the measured run where the checker itself silently skipped two entries.
⟐ Claude Code2026-07-18
I Believed Plan Mode Only Read — Replacing That Belief With Machinery
Claude Code 2.1.212 fixed a bug where plan mode ran file-modifying Bash commands without the permission prompt or the SDK canUseTool callback. Here is what could happen while that assumption was broken, how to verify your own setup, and how to stop leaning on a mode name for safety.
📚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