---
title: "gRPC vs REST for Mobile: Benchmarks, Tradeoffs, and Reality"
published: true
description: "A hands-on walkthrough of gRPC vs REST for mobile backends — real serialization benchmarks, codegen pipeline comparison across Wire, grpc-kotlin, and SwiftProtobuf, and practical guidance for Android, iOS, and KMP teams."
tags: kotlin, android, ios, mobile
canonical_url: https://blog.mvpfactory.co/grpc-vs-rest-for-mobile-benchmarks-tradeoffs-and-reality
---
## What You Will Learn
By the end of this walkthrough, you will understand exactly where gRPC with Protocol Buffers beats REST+JSON on mobile — and where it doesn't. We will cover real serialization benchmarks on mid-range devices, walk through the codegen pipeline options for Android, iOS, and KMP, and I will show you the interceptor pattern that replaces half your custom networking boilerplate.
Here is the short version: gRPC delivers roughly 60% smaller payloads and 30-40% faster serialization than REST+JSON on mobile, but only for structured, repeated-field-heavy payloads. For simple CRUD endpoints, the overhead of HTTP/2 connection setup and protobuf toolchain complexity can negate those wins. The real advantage? The schema-first contract and cross-platform codegen pipeline that kills an entire class of integration bugs across Android, iOS, and KMP.
## Prerequisites
- Familiarity with REST API design and JSON serialization
- Basic experience with either Kotlin (Android/KMP) or Swift (iOS)
- Understanding of HTTP/2 fundamentals (helpful, not required)
## Step 1: Start With the Schema, Not the Code
Here is the gotcha that will save you hours. Most teams treat gRPC adoption as a wire format optimization. It is fundamentally a design discipline. When you define your `.proto` files before writing a single line of Kotlin or Swift, you are forced to think precisely about field types, evolution strategy, and what your API actually promises. Write your `.proto` schemas before any implementation. Treat schema files as the canonical contract.
## Step 2: Understand Where Binary Format Actually Wins
Here are representative benchmarks from mid-range devices (Pixel 6a, iPhone SE 3rd gen) serializing a typical "order list" response with 50 items:
| Metric | REST + JSON | gRPC + Protobuf | Delta |
|---|---|---|---|
| Payload size (wire) | 48.2 KB | 18.7 KB | -61% |
| Serialization (Android, median) | 12.3 ms | 7.1 ms | -42% |
| Deserialization (Android, median) | 14.8 ms | 9.2 ms | -38% |
| Serialization (iOS, median) | 10.1 ms | 6.8 ms | -33% |
| Deserialization (iOS, median) | 11.6 ms | 7.9 ms | -32% |
| Simple single-object GET | 0.4 KB | 0.3 KB + framing | ~negligible |
The docs do not mention this, but binary format wins scale with payload complexity. A single user profile fetch? JSON is fine. A paginated feed with nested objects and repeated fields? Protobuf wins by a wide margin.
## Step 3: Pick Your Codegen Pipeline
Let me show you a pattern I use in every project — choosing the right codegen tool based on your platform target.
| Feature | grpc-kotlin | Wire (Square) | SwiftProtobuf + grpc-swift |
|---|---|---|---|
| Codegen quality | Verbose, complete | Concise, Kotlin-idiomatic | Clean, two-dependency split |
| APK/IPA size impact | ~3-4 MB | ~1-1.5 MB | ~2 MB |
| Streaming support | Full (coroutines + Flow) | Partial | Full (async/await) |
| KMP compatibility | Limited | Excellent | N/A (Swift only) |
| Field evolution / unknown fields | Preserved | Preserved | Preserved |
**grpc-kotlin** produces coroutine-based stubs with `Flow` for streaming. Tightly coupled to the full gRPC runtime, adding roughly 3-4 MB to your APK. Generated code is verbose but complete — interceptors, deadlines, and metadata come out of the box.
**Wire (Square)** takes a different philosophy: minimal generated code, Kotlin-first data classes, no gRPC runtime dependency if you only need serialization. Wire-generated models are roughly 40% smaller in code footprint than the Google protobuf-java output. For KMP projects, Wire is the clear winner — it generates Kotlin multiplatform-compatible code from a single `.proto` definition that compiles for both Android and iOS targets.
**SwiftProtobuf** handles message codegen well, but gRPC service stubs come from grpc-swift, a separate project. Swift's value-type semantics align naturally with protobuf's immutable message model.
## Step 4: Replace WebSockets With Bidirectional Streaming
gRPC's bidirectional streaming over HTTP/2 is a structured alternative to WebSockets for real-time features like chat, live updates, and collaborative editing. Your streaming messages share the same protobuf schema, same interceptor chain for auth and retry, and same observability pipeline.
Here is the minimal setup to get this working: layer your interceptor chain as auth (attaching bearer tokens), retry (exponential backoff on `UNAVAILABLE` status codes), then observability (latency histograms and error rate metrics per RPC method). This composability is one of gRPC's quietly strong points. In REST, you rebuild this per HTTP client library.
## Gotchas
- **gRPC-Web does not support bidirectional streaming.** If your mobile app has a companion web client, you fall back to unary or server-side streaming only in browser or environments without native HTTP/2.
- **Binary payloads are not human-readable** in network inspectors without tooling like `grpcurl` or Buf's reflection. Debugging is genuinely harder.
- **Toolchain complexity is real.** Protobuf compiler, language-specific plugins, build system integration — the setup cost is non-trivial, and every new team member pays it again.
- **Simple CRUD APIs gain little.** If your app is 90% basic resource fetching, REST with a well-typed OpenAPI spec gives you similar type safety with a simpler stack.
## Conclusion
Adopt gRPC for payload-heavy, streaming-heavy, or multi-platform APIs where codegen and binary format compound into real savings. Keep REST for simple public-facing endpoints. Use Wire for KMP projects — its multiplatform codegen and minimal footprint make it the pragmatic choice over the official Google plugin. And always write the `.proto` schema first. The act of writing it precisely will expose design flaws early.
For further actions, you may consider blocking this person and/or reporting abuse
Top comments (0)