Networking & Protocols
intermediate
Weight: 3/10

HTTP REST for IoT

HTTP and REST for embedded/IoT: REST principles, HTTP/1.1 vs HTTP/2, API design for embedded devices, JSON vs CBOR, authentication (API keys, OAuth, JWT), TLS overhead on constrained devices, CoAP for constrained networks, and when REST is appropriate versus lightweight protocols.

networking
http
rest
api
iot
tls
coap

Quick Cap

HTTP and REST are the backbone of the web, and they are increasingly used in IoT for device provisioning, configuration APIs, OTA update coordination, and cloud integration. REST (Representational State Transfer) is an architectural style -- not a protocol -- built on statelessness, resource-oriented URLs, and standard HTTP methods. For embedded engineers, the key interview challenge is understanding when HTTP/REST is the right choice for IoT (configuration, provisioning, dashboards) versus when it is too heavy (high-frequency telemetry, constrained devices) and MQTT or CoAP is a better fit.

Key Facts:

  • REST is an architectural style: Stateless, resource-oriented, uses standard HTTP methods (GET, POST, PUT, DELETE) mapped to CRUD operations
  • HTTP overhead is significant: Text headers add 300-800 bytes per request; TCP connection setup adds latency; TLS handshake adds seconds on slow MCUs
  • HTTP/2: Binary framing, header compression (HPACK), multiplexing -- reduces overhead but requires TLS and more RAM
  • JSON is standard but verbose: CBOR (binary JSON equivalent) is 30-50% smaller and faster to parse on MCUs
  • Authentication options: API keys (simplest), JWT (stateless tokens), OAuth 2.0 (delegated authorization), mutual TLS (strongest for device identity)
  • Best fit for IoT: On-demand operations (provisioning, OTA metadata, configuration) -- not high-frequency telemetry

Deep Dive

At a Glance

ConceptDetail
ProtocolHTTP/1.1 (text-based) or HTTP/2 (binary framing); both over TCP
ArchitectureClient-server, stateless, resource-oriented
Port80 (HTTP), 443 (HTTPS/TLS)
MethodsGET (read), POST (create), PUT (replace), PATCH (partial update), DELETE (remove)
Data formatsJSON (most common), CBOR (binary, compact), XML (legacy), Protocol Buffers
SecurityTLS/HTTPS -- encryption, server authentication, optional client certificates
Embedded clientslibcurl (Linux), lwIP httpd (bare-metal), ESP-IDF HTTP client, Zephyr HTTP
OverheadHigh -- hundreds of bytes of headers, TCP connection cost, TLS handshake

REST Principles

REST is not a protocol -- it is a set of architectural constraints. Understanding these constraints is essential for designing clean APIs and for articulating why REST works well for some IoT scenarios and poorly for others.

PrincipleWhat It MeansWhy It Matters for IoT
StatelessEvery request contains all information needed to process it; the server keeps no per-client state between requestsScales horizontally -- any server instance can handle any request. A device can talk to any backend node without session affinity.
Resource-orientedEvery entity is a resource identified by a URI (/devices/sensor42/config)Natural mapping to IoT: devices, sensors, firmware images, and configurations are all resources with clear URIs.
Uniform interfaceStandard methods (GET, POST, PUT, DELETE) with well-defined semanticsAny developer or tool can interact with the API without custom documentation for basic operations.
RepresentationsResources can have multiple representations (JSON, CBOR, XML) selected via content negotiationA cloud dashboard requests JSON; a constrained device requests CBOR -- same API, different formats.
HATEOASResponses include links to related resources (rarely implemented in IoT)Enables self-describing APIs, but adds overhead that constrained devices rarely need.

HTTP Methods and CRUD Mapping

HTTP MethodCRUD OperationIdempotent?Safe?Example
GETReadYesYesGET /api/v1/devices/sensor42 -- retrieve device info
POSTCreateNoNoPOST /api/v1/devices -- register a new device
PUTReplaceYesNoPUT /api/v1/devices/sensor42/config -- replace entire config
PATCHPartial updateNo*NoPATCH /api/v1/devices/sensor42/config -- update one field
DELETEDeleteYesNoDELETE /api/v1/devices/sensor42 -- deregister device

*PATCH can be made idempotent with proper design, but the spec does not require it.

Idempotency matters in IoT: If a device sends a PUT request to update its configuration but the response is lost (network glitch), the device can safely retry the PUT because applying the same update twice produces the same result. If the device used POST instead, a retry might create a duplicate resource. Design your APIs so that retryable operations use idempotent methods.

Common HTTP status codes for IoT APIs:

CodeMeaningIoT Use
200 OKRequest succeededSuccessful GET, PUT, PATCH
201 CreatedResource createdSuccessful POST (device registration)
204 No ContentSuccess, no bodySuccessful DELETE
400 Bad RequestMalformed requestInvalid JSON, missing required fields
401 UnauthorizedAuthentication requiredMissing or invalid API key/token
403 ForbiddenAuthenticated but not authorizedDevice trying to access another device's resource
404 Not FoundResource does not existUnknown device ID
429 Too Many RequestsRate limit exceededDevice polling too aggressively
503 Service UnavailableServer overloadedBackend maintenance; device should back off and retry

HTTP/1.1 vs HTTP/2 for Embedded

FeatureHTTP/1.1HTTP/2
FramingText-based (human-readable)Binary framing (compact, machine-efficient)
HeadersRepeated verbatim in every requestHPACK compression -- headers sent once, then referenced by index
MultiplexingOne request at a time per connection (head-of-line blocking)Multiple concurrent streams on one connection
Server pushNot supportedServer can push resources before client requests them
TLSOptionalPractically required (all browsers require it; most servers do too)
RAM costLower (simple text parsing)Higher (binary parser, HPACK table, stream management)
Embedded supportUniversal (every HTTP library supports 1.1)Limited (nghttp2, curl, some ESP-IDF builds)

For most embedded IoT devices, HTTP/1.1 is the practical choice. HTTP/2's benefits (header compression, multiplexing) matter when making many requests in parallel -- which is typical for web browsers loading dozens of assets, but not for an IoT device making one API call every few minutes. The added complexity and RAM cost of HTTP/2 rarely justify the benefits on constrained devices.

💡Interview Tip: HTTP/2 and IoT

When asked about HTTP/2 for IoT, acknowledge its benefits (header compression, multiplexing, server push) but explain that the real-world trade-off on constrained devices usually favors HTTP/1.1 for simplicity, or MQTT for efficiency. HTTP/2 makes more sense on embedded Linux gateways that aggregate data from many sensors and make many concurrent API calls to the cloud.

REST API Design for Embedded Devices

Designing APIs that embedded devices will consume requires different considerations than designing for web or mobile clients:

Keep payloads small. A typical REST response for a web app might be 10-50 KB of JSON. An MCU with 64 KB of RAM cannot buffer this. Design endpoints that return only the fields the device needs. Use pagination for lists. Prefer flat JSON structures over deeply nested ones.

Use versioned URLs. Embed the version in the path (/api/v1/...). Devices in the field cannot be updated as easily as web clients. When you release v2 of your API, v1 must continue working for devices that have not received a firmware update.

Design for intermittent connectivity. Devices on cellular or satellite links may have seconds to minutes of connectivity per day. Make endpoints idempotent so retries are safe. Return clear error codes (429, 503) with Retry-After headers so devices know when to try again instead of hammering the server.

Minimize round trips. Every HTTP request on a cellular modem costs power (radio wake-up), time (TCP + TLS handshake), and money (data charges). Batch operations where possible -- one POST with an array of readings is better than 10 individual POSTs.

px-2 py-1 rounded text-sm font-mono border
// Good: batch upload of sensor readings
POST /api/v1/devices/sensor42/readings
Content-Type: application/json
[
{"type": "temperature", "value": 23.5, "ts": 1700000000},
{"type": "humidity", "value": 65.2, "ts": 1700000000},
{"type": "pressure", "value": 1013, "ts": 1700000000}
]

JSON vs CBOR

CriteriaJSONCBOR
FormatText (UTF-8)Binary
SizeVerbose -- keys repeated, numbers as decimal strings30-50% smaller than equivalent JSON
ParsingRequires text parsing (tokenizer, string comparisons)Binary decoding with tag-length-value; fast on MCUs
Human readabilityYes -- easy to debug with curl and browser toolsNo -- requires tools like cbor.me or hex dumps
EcosystemUniversal -- every language, tool, and service supports JSONGrowing -- supported by CoAP, LwM2M, COSE; limited tooling
Embedded librariescJSON, jsmn (both lightweight)tinycbor, QCBOR, cn-cbor
Best forAPIs consumed by web clients and devices; debuggingConstrained devices where bandwidth and parsing speed matter

Practical recommendation: Use JSON for APIs that humans will debug and web clients will consume. Use CBOR on constrained device-to-device or device-to-gateway links where bandwidth is precious. Many IoT architectures use CBOR between sensor and gateway, then the gateway translates to JSON for the cloud API.

Authentication for IoT REST APIs

MethodComplexityStatefulnessSecurityEmbedded Suitability
API keyLowStatelessBasic (key can be stolen if not over TLS)Best for simple devices -- one static key per device, sent in header
JWT (JSON Web Token)MediumStatelessGood -- signed, expirable, contains claimsGood for devices that can do crypto; token expires and must be refreshed
OAuth 2.0HighStateless (tokens)Best -- delegated auth, scoped permissions, token rotationComplex on MCUs; better suited for embedded Linux gateways
Mutual TLS (mTLS)HighStatelessStrongest -- device authenticated by X.509 certificateStandard for AWS IoT, Azure IoT Hub; requires TLS stack with client certificate support

The embedded trade-off: API keys are the simplest to implement -- the device includes X-API-Key: abc123 in every request. But if the key is compromised (extracted from firmware), all devices using that key are compromised. Per-device API keys or mutual TLS (where each device has a unique certificate) are more secure but harder to provision. JWT is a good middle ground: the device authenticates once (with a certificate or credentials), receives a time-limited token, and includes it in subsequent requests.

⚠️Common Trap: Hardcoded API Keys

Never hardcode API keys in firmware that ships to customers. Keys embedded in firmware can be extracted via JTAG, flash dump, or binary analysis. Use a secure element (ATECC608, Infineon OPTIGA) to store per-device credentials, or use a device provisioning flow that generates unique credentials during manufacturing.

TLS/HTTPS Overhead on Constrained Devices

HTTPS (HTTP over TLS) is essential for security, but the costs are significant on MCUs:

ResourceCostNotes
RAM20-40 KB for TLS session + certificate buffersmbedTLS with a 2048-bit RSA certificate; ECC certificates use less
Flash50-100 KB for TLS library (mbedTLS, wolfSSL)Configurable; strip unused cipher suites to reduce size
Handshake time1-5 seconds on Cortex-M4 at 80 MHzRSA key exchange is slow; ECDHE is 2-4x faster
Handshake data5-10 KB (certificate chain, key exchange)Server certificate chain can be 3-5 KB alone
Per-request overhead50-100 bytes (TLS record header, MAC, padding)Minimal once the session is established
Session resumptionSaves 1-2 round trips on reconnectionTLS 1.3 supports 0-RTT resumption; mbedTLS supports session tickets

Strategies to reduce TLS overhead on constrained devices:

  • Use ECC certificates (ECDSA P-256) instead of RSA -- smaller keys, faster handshake, less RAM
  • Enable TLS session resumption so reconnections skip the full handshake
  • Use TLS 1.3 (fewer round trips, mandatory forward secrecy, smaller handshake)
  • Offload TLS to a hardware crypto accelerator (many MCUs have AES, SHA, and ECC hardware)
  • If TLS is truly impossible on the MCU, terminate TLS at a gateway and use a physically secured link between the MCU and gateway

When REST is Appropriate for IoT (and When It Is Not)

This is the critical trade-off question in interviews.

ScenarioREST/HTTPMQTTCoAP
Device provisioningBest -- one-time setup, standard toolingPossible but unnaturalPossible
OTA update metadataBest -- GET the manifest, download the binaryMQTT can deliver URLCoAP block-wise for small updates
Configuration APIBest -- PUT/GET config resources, idempotentPossible with pub/subGood fit for constrained devices
Dashboard / web UIBest -- browsers speak HTTP nativelyRequires WebSocket bridgeRequires HTTP proxy
High-frequency telemetryToo heavy -- connection per request, large headersBest -- persistent connection, 2-byte headerGood -- UDP, 4-byte header
Real-time commandsRequires polling (or WebSocket)Best -- broker pushes to device instantlyGood with Observe
Battery-powered sensorToo heavy -- TCP + TLS per wakeup cycleGood -- persistent connection reuseBest -- UDP, no connection state
Device managementGoodPossibleBest (LwM2M uses CoAP)

The rule of thumb: Use HTTP/REST for the control plane (provisioning, configuration, OTA coordination, monitoring dashboards) and MQTT or CoAP for the data plane (telemetry, events, real-time commands). Many production IoT systems use both -- the device talks MQTT for telemetry and receives configuration via HTTP REST endpoints.

Embedded HTTP Clients

LibraryPlatformRAMNotes
libcurlEmbedded LinuxHigh (200+ KB)Full-featured; supports HTTP/1.1, HTTP/2, TLS, proxies, cookies; the standard for Yocto/Buildroot
lwIP httpdBare-metal / RTOSLow (part of lwIP stack)Simple HTTP server; limited client functionality
ESP-IDF HTTP clientESP32ModerateBuilt-in to ESP-IDF; supports TLS, chunked transfer, basic/bearer auth
Zephyr HTTP clientZephyr RTOSModerateNative Zephyr subsystem; integrates with Zephyr's TLS (mbedTLS)
mongooseAnyModerate (40-100 KB)Embedded web server and client; supports WebSocket, MQTT, HTTP; single-file deployment
tiny-curlConstrainedLower than libcurlStripped-down curl for MCUs; fewer protocols, less configurability

For embedded Linux (Yocto, Buildroot): libcurl is the standard choice. It handles connection pooling, TLS, redirects, and retries. The downside is memory footprint -- it is a full-featured library designed for general-purpose computing.

For bare-metal/RTOS: Most developers use the HTTP client built into their SDK (ESP-IDF, Zephyr, STM32 LwIP). For custom implementations, mongoose provides a single-file HTTP server and client that is easy to integrate.

Debugging Story: The 30-Second OTA Timeout

An IoT gateway running embedded Linux downloaded OTA firmware updates via HTTPS from an S3-compatible cloud storage service. The update process worked reliably in the lab but failed intermittently in the field -- the download would start, transfer 200-300 KB, then stall and eventually time out after 30 seconds with a "connection reset" error.

The lab used a wired Ethernet connection with 50 ms latency and no packet loss. The field devices used LTE-M cellular with 200-500 ms latency and occasional 2-5% packet loss. Investigation revealed two overlapping issues:

First, the HTTP client (libcurl) was configured with a 30-second inactivity timeout (CURLOPT_LOW_SPEED_TIME). On the cellular link, TCP congestion control reacted to packet loss by reducing the window dramatically. After a burst of loss, the TCP window shrank to the point where data transfer slowed below the minimum speed threshold, triggering the timeout. The fix was increasing the timeout to 120 seconds and lowering the minimum speed threshold to 100 bytes/sec.

Second, the cellular modem's TCP window was limited to 16 KB. With a 500 ms RTT, this capped throughput at 32 KB/s regardless of available bandwidth. The 2 MB firmware update took over 60 seconds at best, and any congestion-related slowdown pushed it past the timeout. The fix was enabling TCP window scaling on the modem and increasing the window to 64 KB.

Lesson: HTTP over cellular is fundamentally different from HTTP over Ethernet. TCP congestion control interacts with high-latency, lossy links in ways that desktop developers never encounter. Always test OTA downloads under realistic network conditions (high latency, packet loss, variable bandwidth) and configure timeouts that accommodate the worst-case cellular behavior -- not the best-case lab conditions.

CoAP: REST over UDP for Constrained Devices

CoAP (Constrained Application Protocol, RFC 7252) brings the REST model to devices too constrained for HTTP. It maps GET, PUT, POST, and DELETE to compact binary messages that travel over UDP instead of TCP -- eliminating the connection setup, congestion control overhead, and per-connection RAM that make HTTP impractical on the smallest MCUs. CoAP headers are just 4 bytes (versus hundreds of bytes for HTTP headers), and the entire protocol can run in under 10 KB of RAM. It is the protocol underneath LwM2M (the OMA device management standard) and pairs naturally with CBOR for payload encoding and DTLS for security.

CoAP vs HTTP -- key differences:

CriteriaHTTP/1.1CoAP
TransportTCP (reliable, connection-oriented)UDP (connectionless, lower overhead)
Header size300-800+ bytes (text)4 bytes (binary, compact options)
SecurityTLS over TCPDTLS over UDP
ReliabilityTCP guarantees deliveryApplication-level: CON (confirmable) and NON (non-confirmable) messages
Caching / proxyingBuilt-in (ETags, Cache-Control)Built-in (Max-Age, ETags, proxy support)
DiscoveryDNS / mDNS/.well-known/core resource discovery (CoRE Link Format)
Observe (server push)Not native (requires WebSocket or SSE)Built-in Observe option -- server pushes updates on resource change
Best fitEmbedded Linux, gateways, cloud APIsCortex-M, 6LoWPAN/Thread sensors, battery-powered endpoints

CoAP defines two message types for reliability control. CON (Confirmable) messages require an ACK from the receiver -- if no ACK arrives, CoAP retransmits with exponential backoff (similar to TCP but at the application layer, with far less state). NON (Non-confirmable) messages are fire-and-forget, like UDP itself -- ideal for periodic sensor readings where the next value replaces the last. This per-message reliability choice gives embedded developers fine-grained control that TCP's all-or-nothing reliability cannot provide. A single device can send critical alerts as CON and routine telemetry as NON, optimizing battery life without giving up reliability where it matters.

The Observe pattern is CoAP's answer to HTTP polling. A client sends a GET request with an Observe option registered. The server then pushes notifications whenever the resource changes -- without the client polling repeatedly. This is transformative for battery-powered sensors: instead of a monitoring dashboard polling 100 sensors every 5 seconds (100 request-response round trips), the sensors push updates only when values change. On a 6LoWPAN mesh network where every packet costs radio time and battery, Observe can reduce traffic by 90% or more compared to HTTP polling.

In practice, CoAP is most commonly deployed on IEEE 802.15.4 / 6LoWPAN / Thread networks where IPv6 packets are compressed to fit in 127-byte radio frames and every byte of protocol overhead matters. A CoAP-to-HTTP proxy at the border router translates between the constrained network and standard REST infrastructure, letting cloud services consume sensor data via normal HTTP while the sensors themselves use CoAP's minimal footprint. Libraries like libcoap, microcoap, and Zephyr's CoAP subsystem provide lightweight implementations for Cortex-M targets, typically requiring 5-15 KB of flash and 2-5 KB of RAM.

What interviewers want to hear: You understand REST principles (statelessness, resources, uniform interface) and can explain why they matter for IoT API design. You can map CRUD to HTTP methods and explain idempotency. You know HTTP/1.1 vs HTTP/2 trade-offs with embedded context. You can compare JSON and CBOR for constrained devices. You understand authentication options (API keys, JWT, mTLS) and their embedded trade-offs. Critically, you know when REST is the right choice (control plane: provisioning, configuration, OTA) and when it is too heavy (data plane: telemetry, events) -- and you can articulate this trade-off with concrete reasoning about header size, connection overhead, power consumption, and server push capability.

Interview Focus

Classic HTTP/REST Interview Questions

Q1: "What are the core REST principles, and why does statelessness matter for IoT?"

Model Answer Starter: "REST is built on statelessness, resource orientation, a uniform interface (standard HTTP methods), and representations. Statelessness means every request contains all information needed to process it -- the server stores no per-client session state. This matters for IoT because it enables horizontal scaling: when 100,000 devices are calling your API, any backend server can handle any request without needing session affinity. It also simplifies device firmware -- the device does not need to track session state or handle session expiry. The trade-off is that every request must include authentication credentials, which adds per-request overhead."

Q2: "When would you use HTTP/REST for an IoT device versus MQTT?"

Model Answer Starter: "I use HTTP/REST for the control plane -- device provisioning, configuration retrieval, OTA update manifest download, and any interaction where standard web tooling and caching are valuable. HTTP is request/response and stateless, which maps naturally to read-config-then-apply operations. I use MQTT for the data plane -- continuous telemetry, event notifications, and real-time commands -- because MQTT's persistent TCP connection, 2-byte header, and pub/sub model are dramatically more efficient for high-frequency, bidirectional data flow. Many production systems use both: the device fetches its configuration via HTTPS on boot, then opens an MQTT connection for ongoing telemetry and commands."

Q3: "How does TLS impact an embedded device, and how would you reduce its overhead?"

Model Answer Starter: "TLS adds 20-40 KB of RAM for session state and certificate buffers, 50-100 KB of flash for the library, and 1-5 seconds for the handshake on a Cortex-M4. I reduce this by using ECC certificates instead of RSA (smaller keys, faster math), enabling TLS session resumption so reconnections skip the full handshake, using TLS 1.3 which has fewer round trips, and offloading crypto to hardware accelerators (many MCUs have AES and SHA peripherals). If the device is too constrained for TLS, I terminate TLS at a gateway and secure the MCU-to-gateway link physically or with a lightweight symmetric cipher."

Q4: "What is the difference between JSON and CBOR, and when would you use each?"

Model Answer Starter: "JSON is text-based, human-readable, and universally supported by cloud services and web tools. CBOR is a binary encoding that is semantically equivalent to JSON but 30-50% smaller and faster to parse because it uses tag-length-value encoding instead of text tokenization. I use JSON for APIs that humans debug frequently and that web clients consume. I use CBOR on constrained device-to-gateway links where bandwidth is limited and every byte counts -- for example, sensor readings sent over NB-IoT where data costs money per byte. Many architectures translate CBOR to JSON at the gateway."

Q5: "How would you design a REST API for an IoT device fleet?"

Model Answer Starter: "I would version the API in the URL path (/api/v1/...) because field devices cannot be updated as easily as web clients. Resources map to IoT entities: /api/v1/devices/{id} for device info, /api/v1/devices/{id}/config for configuration, /api/v1/devices/{id}/firmware for OTA. I would use PUT for configuration updates (idempotent, safe to retry), POST for telemetry data submission (creates a new reading), and GET for status checks. Payloads would be compact JSON with only necessary fields. I would return proper status codes -- 429 with Retry-After for rate limiting, 503 for maintenance -- so devices implement exponential backoff rather than hammering the server. For authentication, I would use per-device API keys for simplicity or mutual TLS for stronger identity."

Trap Alerts

  • Don't say: "Just use HTTP for everything in IoT." HTTP's text headers, TCP connection overhead, and client-pull model make it a poor choice for high-frequency telemetry or real-time commands. Knowing when NOT to use HTTP is as important as knowing how to use it.
  • Don't forget: Idempotency. IoT devices operate on unreliable networks and will retry requests. If your API uses POST for an operation that should be idempotent (like updating configuration), a retry creates a duplicate. Use PUT or PATCH for updates.
  • Don't ignore: TLS overhead. Saying "just add HTTPS" without acknowledging the RAM, flash, and CPU cost shows you have not worked on constrained devices. An MCU with 64 KB RAM may not have room for both TLS and the application.

Follow-up Questions

  • "How would you handle OTA firmware updates over HTTP for a fleet of 10,000 devices?"
  • "What is the difference between HTTP keep-alive and a persistent MQTT connection?"
  • "How would you implement rate limiting on an IoT REST API?"
  • "What is content negotiation in HTTP, and how would you use it to serve both JSON and CBOR from the same endpoint?"

Practice

Which REST principle means the server stores no per-client session state between requests?

Which HTTP method is idempotent and used to replace an entire resource?

Why is CBOR preferred over JSON on constrained IoT devices?

What is the approximate RAM cost of adding TLS (HTTPS) on a Cortex-M device?

For which IoT scenario is HTTP/REST the BEST fit?

Real-World Tie-In

OTA Update Coordination -- A fleet of 50,000 smart thermostats used HTTPS REST to check for firmware updates. Each device called GET /api/v1/devices/{id}/firmware/latest on boot and once daily, receiving a JSON manifest with the firmware version, SHA-256 checksum, and download URL. If a new version was available, the device downloaded the binary from a CDN via HTTPS. The REST API served the manifest (1 KB) cheaply, while the CDN handled the bulk transfer. Using REST for the metadata and CDN for the binary kept the API server's load manageable across 50,000 devices.

Hybrid MQTT plus REST Architecture -- An industrial IoT platform used MQTT for continuous machine telemetry (vibration, temperature, power consumption at 1 Hz) and REST for the management plane. Operators used a web dashboard that called REST endpoints to query device status (GET /api/v1/machines/{id}), update alert thresholds (PUT /api/v1/machines/{id}/config), and trigger diagnostics (POST /api/v1/machines/{id}/diagnostics). The gateway translated between MQTT on the factory floor and REST for the cloud. This separation kept the data plane efficient (MQTT's 2-byte header, persistent connection) while giving the management plane the benefits of standard HTTP tooling, caching, and browser compatibility.

Cellular Asset Tracker with Batch Upload -- A logistics company deployed LTE-M GPS trackers on shipping containers. Each tracker accumulated 24 hours of GPS readings (latitude, longitude, timestamp) in flash memory, then connected once per day via cellular and uploaded all readings in a single POST /api/v1/trackers/{id}/positions request with a JSON array. Batching was critical: each cellular connection cost 5 seconds of radio time (TCP + TLS handshake) and data charges per KB. Sending one request with 288 readings (one per 5 minutes) cost the same connection overhead as sending 288 individual requests but used 1/288th of the radio wake-ups.