Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Envoy Mobile & the upcoming networking revolution
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Michael Rebello
November 29, 2019
Programming
130
2
Share
Envoy Mobile & the upcoming networking revolution
Talk given at Swiftable in Buenos Aires, Argentina in November 2019.
Michael Rebello
November 29, 2019
Other Decks in Programming
See All in Programming
20260514 - build with ai 2026 - build LINE Bot with Gemini CLI
line_developers_tw
PRO
0
440
t *testing.T は どこからやってくるの?
otakakot
1
940
Spec Driven Development | AI Summit Vilnius
danielsogl
PRO
1
160
JCON - Create Agentic AI Apps, The Easy Way!
kdubois
1
110
2026年のソフトウェア開発を考える(2026/05版) / Software Engineering Scrum Fest Niigata 2026 Edition
twada
PRO
23
12k
KMP × Kotlin 2.3 - How Android Got Slower While iOS Builds Improved by 47%
rio432
0
190
AWSはOSSをどのように 考えているのか?
akihisaikeda
0
120
cloudnative conference 2026 flyle
azihsoyn
0
180
GitHubCopilotCLIをはじめよう.pdf
htkym
0
330
Kubernetesを使わない環境にもCloud Nativeなデプロイを実現する / Enabling Cloud Native deployments without the complexity of Kubernetes
linyows
3
390
運転動画を検索可能にする〜Cosmos-Embed1とDatabricks Vector Searchで〜/cosmos-embed1-databricks-vector-search
studio_graph
3
910
要はバランスからの卒業 #yumemi_grow
kajitack
0
160
Featured
See All Featured
We Are The Robots
honzajavorek
0
230
Visual Storytelling: How to be a Superhuman Communicator
reverentgeek
2
530
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.7k
Code Reviewing Like a Champion
maltzj
528
40k
AI Search: Implications for SEO and How to Move Forward - #ShenzhenSEOConference
aleyda
1
1.2k
Testing 201, or: Great Expectations
jmmastey
46
8.1k
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
180
Why Your Marketing Sucks and What You Can Do About It - Sophie Logan
marketingsoph
0
140
GraphQLの誤解/rethinking-graphql
sonatard
75
12k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
287
14k
We Have a Design System, Now What?
morganepeng
55
8.1k
Transcript
Envoy Mobile & the upcoming networking revolution Michael Rebello @rebello95
Swiftable (Buenos Aires) - November 2019
Service Networking Networking iOS
Service Flask, etc. URLSession iOS
Service Library X Library X iOS
Service Envoy Envoy Mobile iOS
Let’s talk about what data we send, then come back
to how we send it.
Early API workflow at Lyft Tech spec handwritten.swift handwritten.kt handwritten.py/.go
let params: [String: Any] = [ "lat": position.latitude, "lng": position.longitude,
"some_param": true, ] client.request(.post, "/foo", parameters: params) { result in … } Early APIs at Lyft
• Handwritten code led to mistakes/typos Problems
iOS Server { “key_a”: “hello” } Programming errors
iOS Server { “key_a”: “hello” } Android { “kye_a”: “hello”
} Programming errors
iOS Server { “key_a”: “hello” } Android { “kye_a”: “hello”
} if (android): else: Programming errors
• Handwritten code led to mistakes/typos • No visibility into
deserialization failures Problems
import Mapper extension FooResponse: Mappable { init(map: Mapper) throws {
self.placeID = try map.from("place_id") let item: String? = map.optionalFrom("items") self.placeDisplay = map.optionalFrom("display.lien_two") } } Deserialization failures
import Mapper extension FooResponse: Mappable { init(map: Mapper) throws {
self.placeID = try map.from("place_id") let item: String? = map.optionalFrom("items") self.placeDisplay = map.optionalFrom("display.lien_two") } } Deserialization failures
import Mapper extension FooResponse: Mappable { init(map: Mapper) throws {
self.placeID = try map.from("place_id") let item: String? = map.optionalFrom("items") self.placeDisplay = map.optionalFrom("display.lien_two") } } Deserialization failures
• Handwritten code led to mistakes/typos • No visibility into
deserialization failures • No single source of truth Problems
YAML integration
paths: /foo: post: parameters: - in: body schema: $ref: '#/definitions/FooRequest'
responses: 200: schema: $ref: '#/definitions/FooResponse' YAML definitions
• Manual code generation for Android • No integration on
iOS or services • Still inconsistencies across platforms • No single source of truth YAML results
Consistency
We needed a source of truth that provided guarantees for
the behavior of any given API.
IDL & protobuf
Interface Definition Language IDL
Old workflow Tech spec handwritten.swift handwritten.kt handwritten.py/.go
Envisioned workflow Tech spec IDL repo foo_api.swift foo_api.kt foo_api.py/.go foo_api.proto
Platform-neutral IDL for defining and serializing APIs. Protocol buffers (“protobufs”)
• Simple to write • Open-source generators available for most
popular languages • JSON support • Optimized wire encoding Why protobuf?
Intro to protobuf
message FooRequest { … } message FooResponse { int64 id
= 1; string first_name = 2; } service Foo { rpc UpdateFoo(FooRequest) returns (FooResponse) { option (http.http_options).path = "/foo"; option (http.http_options).method = "POST"; } } Protobuf definition
message FooRequest { … } message FooResponse { int64 id
= 1; string first_name = 2; } service Foo { rpc UpdateFoo(FooRequest) returns (FooResponse) { option (http.http_options).path = "/foo"; option (http.http_options).method = "POST"; } } Protobuf messages
message FooRequest { … } message FooResponse { int64 id
= 1; string first_name = 2; } service Foo { rpc UpdateFoo(FooRequest) returns (FooResponse) { option (http.http_options).path = "/foo"; option (http.http_options).method = "POST"; } } Protobuf fields
message FooRequest { … } message FooResponse { int64 id
= 1; string first_name = 2; } service Foo { rpc UpdateFoo(FooRequest) returns (FooResponse) { option (http.http_options).path = "/foo"; option (http.http_options).method = "POST"; } } Protobuf services
message FooRequest { … } message FooResponse { int64 id
= 1; string first_name = 2; } service Foo { rpc UpdateFoo(FooRequest) returns (FooResponse) { option (http.http_options).path = "/foo"; option (http.http_options).method = "POST"; } } Protobuf RPCs (Remote Procedure Calls)
message FooRequest { … } message FooResponse { int64 id
= 1; string first_name = 2; } service Foo { rpc UpdateFoo(FooRequest) returns (FooResponse) { option (http.http_options).path = "/foo"; option (http.http_options).method = "POST"; } } Protobuf annotations
IDL pipeline /api/foo.proto Generators +7 others foo.go foo.py foo.kt foo.swift
IDL pipeline /api/foo.proto Generators +7 others foo.go foo.py foo.kt foo.swift
FooV1API library foo-v1-api library
Using protobuf in Swift
// Modules/FooV1API/FooAPI.swift public struct FooRequest: Codable, Equatable { … }
public struct FooResponse: Codable, Equatable { public let id: Int64 public let firstName: String } Generated models
// Modules/FooV1API/FooAPI.swift import RxSwift public protocol FooAPI { func updateFoo(_
request: FooRequest) -> Single<Result<FooResponse, FooAPIError>> } public struct FooClientAPI: FooAPI { // Abstracted implementation } Generated APIs
// Modules/FooV1API/FooAPI.swift import RxSwift public protocol FooAPI { func updateFoo(_
request: FooRequest) -> Single<Result<FooResponse, FooAPIError>> } public struct FooClientAPI: FooAPI { // Abstracted implementation } Generated APIs
// Modules/FooV1APIMock/FooAPI.swift open class FooMockAPI: FooAPI { open lazy var
mockUpdateFoo: (FooRequest) -> Result<FooResponse, FooAPIError> = { … } open func updateFoo(_ request: FooRequest) -> Single<Result<FooResponse, FooAPIError>> { … } } Generated mocks
// Modules/FooFeatureModule/FooFeature.swift getFooClientAPI() .updateFoo(FooRequest(...)) .subscribe({ result in switch result {
case .success(let response): // Consume the response case .failure(let error): // Handle the failure } }) .disposed(by: self.disposeBag) Using APIs
★ Single source of truth for all APIs ★ Consistent
interfaces across platforms ★ Ergonomic generated code on all platforms ★ Highly testable ★ Wire format fully abstracted Results
Optimizing transport: Content negotiation
Client Service JSON request Existing system JSON response
Client Service JSON request Content-Type: json Accept: x-protobuf,json Content negotiation
Middleware (service) JSON > Protobuf Protobuf request Content-Type: x-protobuf Protobuf response Content-Type: x-protobuf Middleware (service) No change Protobuf response Content-Type: x-protobuf
JSON Protobuf
• 40%+ reduction in payload sizes • Faster response times
• Higher success rates • Transparent to engineers Wins from protobuf
What if we want to change how we send data
rather than what we send?
C++ proxy that abstracts networking from services
Envoy service mesh Service A Proxy Service B Proxy HTTP/1.1,
HTTP/2, gRPC, etc. HTTP/1.1, HTTP/2, gRPC, etc.
Envoy filters Common functionality executed on each request or response
Envoy filters Service A Filter Add auth headers Filter gzip
request Proxy Proxy Filter Unzip payload Filter Validate auth headers Service B
Envoy service mesh + front proxy Service A Proxy Service
B Proxy HTTP/1.1, HTTP/2, gRPC, etc. Client Proxy
Service Library X Library X iOS
None
Service A Proxy Service B Proxy Proxy Client Mobile
• 1 network stack for all platforms • Write filter
functionality once, deploy everywhere • Support new protocols like HTTP/3 (QUIC) • Consistent stats/monitoring across all platforms Envoy Mobile!
Stats Real-time requests from Envoy Mobile on Lyft rider (alpha)
Envoy Mobile will revolutionize how we enable network consistency across
all platforms.
envoy-mobile.github.io @rebello95 Join us!