Why a small transfer costs more than it looks
Mobile radios save power by dropping into low-power states when they are idle, and waking them takes time. To avoid paying that delay on every request, a radio stays powered for a while after each transfer in case more traffic follows. Apple’s Energy Efficiency Guide describes the pattern for cellular and Wi-Fi radios: they power up for the activity, stay up while it runs, and remain up “for an additional period of time in anticipation of more work”. Sporadic transactions, it says, carry high overhead.
That lingering period is the hidden cost. Android’s guide to optimising network access works through an example using AT&T’s timings for a typical 3G radio. After a transfer, the radio stays at full power for 5 seconds of tail time and then spends 12 seconds in a low-power state, so every transfer session keeps the radio drawing energy for at least 18 seconds. An app that makes a one-second transfer three times a minute keeps the radio permanently awake. If the same app bundled its work into one three-second transfer a minute, the radio would be at high power for 20 seconds of each minute and on standby for the other 40.
The timings vary by radio and network, and the guide presents its numbers as representative of 3G. The principle it draws applies to all wireless radios: the number of separate transfer sessions matters, not only the number of bytes.
What the platform guides recommend
Both major mobile platforms tell developers to batch:
- Android calls bundling transfers, so that more data moves less often, “one of the best ways to improve battery efficiency”, and names logs and analytics as data that suits batching well.
- Apple’s guide says apps should batch transactions and let the system defer nonessential network activity to better times, such as when the device is plugged in or on Wi-Fi. One of its examples is downloading several emails at once instead of fetching each as it is opened.
- Android’s WorkManager can hold background work until conditions the developer sets are met, such as the device charging and being connected to Wi-Fi.
The operating systems also batch on the app’s behalf. Android’s Doze mode, which starts when a device is unplugged, stationary and has its screen off, cuts apps off from the network and defers their jobs and syncs to periodic maintenance windows, which come less frequently the longer the device stays idle. App Standby defers background network activity for apps the user has not used recently. Work that is already batched fits into those windows. Work that expects to send every event the moment it happens does not.
Where the bandwidth saving comes from
The OpenTelemetry Collector’s batch processor, which groups spans, metrics and logs before they are exported, gives two reasons for batching: it “helps better compress the data and reduce the number of outgoing connections required to transmit the data.”
Compression works by finding repetition, and a batch of telemetry records with the same field names and similar values contains far more repetition than a single record. Each separate request also carries its own protocol overhead, which a batch pays once instead of once per record. Apple’s guide adds two related habits: compress data before sending it, and resume interrupted transfers rather than starting them again.
What batching costs
Batching trades immediacy and simplicity for efficiency, and each trade needs a decision:
- Delay. Data waits until the batch is full or a timer fires. The OpenTelemetry processor makes both triggers configurable: a size that sends a batch regardless of the timeout, and a timeout that sends it regardless of size. Data a person is waiting to see should not sit in a batch.
- Data at risk. Records held only in memory are lost if the app is stopped before the upload. Batches that may wait a long time belong in durable storage, such as an outbox, and should be removed only after the receiver confirms them.
- Oversized uploads. A batch that keeps growing can become too large for one request. The OpenTelemetry processor has a separate maximum size that splits large batches into smaller ones.
- Wasted work. Drop data before batching it, not after. The OpenTelemetry documentation places the batch processor after any sampling for this reason.
Prefetching, the download-side version of the same idea, has its own trade-off: Android warns that prefetching too aggressively spends battery and bandwidth on data that is never used.
Batching data that waits for a link
On a device without a steady connection, batching stops being only an optimisation. Readings and events build up while there is no link and leave together when one appears, which is the store-and-forward pattern. The design questions are the same as above, with longer waits: where the batch is kept, how large it may grow, what happens when storage fills, and how a retried upload avoids creating duplicates on the server, for example by giving each record a stable identifier so that a repeat is idempotent.
Offline Protocol’s mesh SDK handles its optional telemetry this way. Once an app calls enableTelemetry, the SDK collects events into batches that wait while there is no link, and it uploads them itself when it can.