The iOS Connection Limit and Token Refresh Race Conditions in Flutter
I recently hit a wall when testing our mobile app initialization under bad network conditions and expired auth states. When you launch a modern app, you usually fire off a handful of asynchronous requests immediately: fetching the user profile, remote configs, telemetry, maybe unread notification counts.
If your JSON Web Token (JWT) is expired, every single one of those parallel requests fails instantly.
The Queue Collapse
The problem gets nasty when you factor in native OS constraints. The iOS URLSession strictly limits concurrent HTTP requests to a single host (historically defaulting to 6).
If you fire 10 requests at startup, iOS queues the last 4. When the first 6 requests fail with 401 Unauthorized, your Dio HTTP interceptor (if written naively) intercepts all 6 failures independently. Suddenly, you have 6 simultaneous token refresh requests hitting your backend. The queue locks up, your latency spikes through the roof, and the final 4 requests are left hanging while the backend thrashes through redundant refresh payloads.
The Static Completer Fix
I realized the interception layer needs to be state-aware. We can't let individual UI widgets blindly retry when the global auth state is broken.
The fix is surprisingly simple once you see it: a static Completer (or a cached Future) inside the interceptor's memory space.
When the very first 401 hits, I check a static isRefreshing boolean. If it's false, I flip it to true, initialize the Completer, and execute the single token refresh API call.
If the boolean is already true (meaning a parallel request is currently trying to refresh the token), the interceptor forcefully halts the execution of that specific request by calling await completer.future.
Once the primary refresh finishes, I update the secure storage, resolve the Completer, flip the boolean back, and recursively retry all suspended requests with the new token.
No matter how many widgets independently request data on startup, only a single refresh payload ever touches the backend. It completely bypasses the iOS URLSession queue bottleneck and keeps the app fluid.
the underlying technology used to scale clothshift and handle 400,000+ users on past exits is available as a boilerplate.
the 'operator_arsenal' and 'root_system' packages include a built-in backend wallet and transaction system fully synchronized across mobile and frontend out of the box.