Most of it breaks below the broker.

Engineers who built and scaled parts of Courier, the open-source MQTT platform behind one of Southeast Asia's largest super-apps, load tested to a million concurrent connections.

Five ceilings on the way to a million. Four broke below the broker, two of those at the load balancer. /  Load test, not a production peak.

Evidence

Five ceilings on the way to a million.

Vendor benchmarks publish the ceiling and not the road to it. Five ceilings, each one at the layer where it actually broke.The broker's own was the fourth of the five. That is why a diagnosis starts below the layer you suspect.

Ceilings hit on the way to one million concurrent MQTT connections, with the layer each one broke at. Source: Acing 1 Million Concurrent MQTT Connections, gojek.io, published 2022-04-15. This was a load test, not a production peak.
ConnectionsLayerWhat broke
28,200 / VMHost and kernelephemeral port exhaustion
40,000Host and kernelEMFILE, file descriptor limit
113,000Load balancerHAProxy port exhaustion
710,000Load balancerHAProxy maxconn cap, raised
362,000BrokerVerneMQ listener limit
Source: Acing 1 Million Concurrent MQTT Connections, gojek.io, published 2022-04-15.Load test. Not a production peak.

Three opinions

Our point of view.

01

Start at the business SLA, not the protocol.

The only one of these that works on someone who is not an engineer. What has to arrive, how fast, and what it costs when it does not, before anyone opens a broker config.

02

The broker is rarely the problem.

Sometimes it genuinely is the broker: the VerneMQ listener limit at 362,000 was real, and forking it was the fix. We still check the layers underneath first, because four of the five ceilings were down there and two of those were the load balancer.gojek.io, 2022-04-15

03

If you cannot say what your push delivery rate is, you do not have one.

A delivery rate nobody has measured is an assumption with a number attached. FIG. 2 below is what the measured version looks like.gojek.io, 2023-10-23

Fig. 2

Push delivery, measured.

Push notification services alone against an MQTT-first path that falls back to them. The axis is truncated, because the whole argument lives in the last thirty points of it.

Measured push delivery rates. Source: gojek.io, published 2023-10-23. The horizontal axis begins at 70 percent, not zero.
PathMeasured delivery
push alone, FCM and APNs, no persistent socket75 to 85 percent
mqtt-first, push fallback, consumer app95 percent or better
mqtt-first, push fallback, driver and merchant apps99 percent or better
Axis begins at 70%, not zero. Marks are measured intervals and floors, not totals.Source: gojek.io, published 2023-10-23.

What we do

Reliable real-time between an app and the backend behind it.

Messages that arrive, on real networks and real handsets, without burning the battery or falling over at the connection count you need. We are a consultancy of engineers who work on every layer that decides whether they do: the client, the radio, the reconnect, the load balancer, the kernel, the broker's internals.

01

Broker scaling and capacity planning

Your broker stops falling over at the connection count you need, and you know where the next ceiling is before you hit it. Which layer sets it, and what it costs to move it. In practice that means MQTT brokers, and VerneMQ is the one we have taken apart.

02

Debugging connection-level incidents

Someone can find the cause when connections silently stop delivering and nothing is obviously broken. Half-open sockets, silent reconnect storms, QoS 1 that is acknowledged and still does not arrive.

03

Staying connected on Android without draining the battery

The app holds its connection instead of being killed by the OS. Doze, background execution limits, and MQTT keepalive intervals that survive a real handset rather than an emulator.

04

Broker modification and forking

The broker behaves the way your architecture needs, instead of the architecture bending around the broker. When the ceiling is inside it and the upstream answer is not coming. gojek/vernemq is public; that is what this looks like.

Not ours, and we will say so early: MQTT 5, browser or web real-time, industrial, automotive.

On the record

Public, dated, checkable in a minute.

The 900-Second Ghost: Debugging Half-Open TCP

KubeCon + CloudNativeCon India and PlatformCon.

Talk / 2026

Acing 1 Million Concurrent MQTT Connections

The source for FIG. 1: all five ceilings in full, with the fix for each one.gojek.io

Write-up / 2022-04-15

More of it, annotated: the eight Courier posts written by members of this team are listed on writing, each with a figure taken from it and a line on what it is evidence for.

Who we are

Four people, four layers.

A message crosses the app, the radio, the network, the load balancer, the kernel and the broker before anyone sees it. The team is shaped the same way.

Ajat Prabha

Server-side and Go

Works on the backend half of the connection. They published the first release of the open source Go client and are its second-highest committer at 78 commits.gojek/courier-go contributors, observed 2026-08-08

Dhruv Jain

Broker operations, and below

Works under the protocol: TCP, kernel limits, load balancers, connection tracking. They authored the load-test write-up FIG. 1 is drawn from, and hold the only independently verified conference speaking credit here.gojek.io, 2022-04-15 / KubeCon + CloudNativeCon India and PlatformCon, 2026

Deepanshu

Android and the mobile client

Works on keeping an app connected on a handset that is trying to sleep. They are the most published author on the Courier series.Courier blog index, observed 2026-08-08

Anubhav Gupta

Mobile real-time architecture

Works on which transport a product should be betting on. They wrote the post that introduced Courier publicly and made the architectural case for MQTT over gRPC and WebSocket on battery grounds.gojek.io, 2021-08-10

How an engagement is staffed: one principal leads it end to end, and the others are scheduled in as named specialist depth where their layer is in scope.

How to start

A connection-layer assessment.

Fixed scope, two to three weeks. It ends in a written diagnosis and a prioritised fix plan that you keep, whether or not anything follows it.

The shape of it: we diagnose, design, modify and hand back, and every engagement carries a written exit condition agreed at the start.