Event-based APIs are becoming more popular, enabling developers to craft new integrations and solutions that go beyond the original design of an API. Yet, there remains a challenge: how can teams design thoughtful event-based APIs that are long-lasting, evolvable, and discoverable? This talk will dive into the design practices of event-based APIs, including tips for determining which protocol(s) you should select, design patterns we should apply, and anti-patterns should we avoid. We will also look at how AI and tools such as ChatGPT are starting to shape the next generation of APIs.
Delivered on May 10, 2023 for the EDA Summit
2. • API Architecture, Strategy, and Execution
• Based in Colorado Springs
• Across multiple verticals:
• Commercial Insurance
• Healthcare
• Hospitality
• Finance and Banking
• Travel
• Airline
Brief Introduction
Photo by Ian Baldwin on Unsplash
3. API design is an
architectural concern
that combines business,
product design, and
software engineering
5. Notification Problem: API Polling is Wasteful
App API
98.5% of polling API requests send back
data that hasn’t changed.
https://nordicapis.com/stop-polling-and-consider-using-rest-hooks/
7. 7
Three Types of Messages
Calculate the
30-day sales
average
Component A
<Message Producer>
Component B
<Message Receiver>
Command Message:
30-day sales
average report
scheduled
Component A
<Message Receiver>
Component B
<Message Producer>
Reply Message:
30-day sales
average
updated
Component A
<Message Producer>
Component B
<Message Receiver>
Event Message:
8. 8
Messages in Practice: Web APIs
GET /books
Accept: application/json
…
<empty>
Command Message
Protocol
Semantics
Request
Body
HTTP Request
200 OK
Content-Type:
application/json
…
{
"books": [
"title":"My book title",
…
]
}
Reply Message
Protocol
Semantics
Response
Body
HTTP Response
9. • Ask what kinds of questions the event needs to answer:
• What happened?
• Who did it happen to?
• Why did it occur?
• Example #1:
• Example #2:
Event Messages
_____
10. Traditional Message Brokers: Queues and Topics
Point-to-Point Messaging
via Queues
Fanout (Pub/Sub)
via Topics
Component
Message
Broker
Component
Publisher
Message
Broker
Subscriber
Subscriber
Subscriber
Component
Message B
Message A
Message A
Message B
Message A
Message A
Message A
Message A
Event-Driven Architecture (EDA) has
leveraged these patterns for decades.
11. Distributed Logs - Apache Kafka and Apache Pulsar
Topic A
Record
1
Record
2
Record
3
Record
4
Record
5
Record
6
Record
7
Record
8
Record
9
Record
10
Consumer B
Consumer A
Distributed Logs combine Fanout with historical record often
not available in traditional message brokers
12. Let’s learn how we can apply the same patterns to APIs
12
Photo by Thought Catalog on Unsplash
18. gRPC Client and Server Streaming
gRPC Client gRPC Server
service Main {
rpc GetLatestOrders(stream OrderQuery)
returns (OrderResults) {}
}
gRPC Async Option 1: Client Streams to
Server
gRPC Client gRPC Server
gRPC Option 2: Server Streams to Client
service Main {
rpc GetLatestOrders(OrderQuery)
returns (stream Order) {}
}
gRPC Client gRPC Server
gRPC Async Option 3: Bi-Directional streaming
service Main {
rpc GetLatestOrders(stream OrderQuery)
returns (stream Order) {}
}
20. ”…if you’re going to start emitting events from a
piece of software, put just as much care into
[event design] as you would as you do in
specifying an API. Because event formats are a
contract, too.”
– Tim Bray
https://www.tbray.org/ongoing/When/201x/2019/11/17/Bits-On-the-Wire
23. Thin Event Notification (aka “Thin Events”)
• Broadcast only the necessary details to notify that
an event occurred
• Forces subscribers to fetch additional details to
complete a task
Use when:
• The desire is to prevent subscribers processing
stale data. They are forced to fetch the latest data
due to frequent changes or potentially delayed
processing
25. Hypermedia-Driven Events
• Include hypermedia links in event
payloads
• Helps consumers find the right
API for details
Use when:
• You wish to bridge event
notifications with API integration
27. Event-Carried State Transfer
• Broadcasts all known data at the time of the event
• Often contain the entire record, avoiding the need to
contact the source system to conduct further work
Use when:
• Subscribers want a snapshot of the data with the event
• Sharing data state changes through message streaming
(Apache Kafka, Apache Pulsar, etc.) to support replaying
message history.
• Using event sourcing /CQRS to capture state changes
over time
29. Structured Event Payloads
• Groups properties as nested structures
• Avoids flat structures that require subscribers to
figure out how properties are grouped
• Helps drive evolvability as property names are
scoped to the parent property (e.g.
addressLine1)
Use when:
• Event payloads require complex data structures
• Event payloads have nested 1-to-many
relationships as part of an event payload
31. Evolutionary Event Schema
• Only add new payload properties that have
default values or are not required
• Don’t delete existing properties unless they
offer a default value (even when missing in
future events)
• Don’t rename property names
Use when:
• When you need to make changes to your
event payload structure but don’t want to
break existing subscribers
33. Offline and Error Recovery Support
• Supplement event notification channels with
APIs that allow offline consumers to catch-
up
• Also allows consumers to identify and
troubleshoot failed deliveries
Use when:
• When offline support is necessary to keep
consumers in-sync
• Manual recovery may be needed during
development or for troubleshooting
34. 35
Leverage Recovery Support in Async Styles
App API
Disconnected
• Another option is to support recovery in the
API itself
• Server-Sent Events has this built-in
• Your API may need to apply a similar
pattern
Use when:
• When offline support is necessary to keep
consumers in-sync
• Recovery after a network failure needs to
be automated
36. Separate Internal and External Events
• Design internal events for coordinating
implementation details
• Design external events for notification and
extensibility
Use when:
• Event-driven architecture is being used
internally, but external events are desired
• Prevent leaking implementation details or
special knowledge of how your internal
systems operate
{
"event": {
"type": "paymentProcessed",
"orderId" : "abc123",
...
}
}
{
"eventType": "authorized",
"transactionId" : "ffe36193abc",
"authorizationServer": "auth7.mycompany.com",
"merchantId" : ”m0043286410",
"transactionAmountInCents" : "20899",
"transactionCurrency" : "USD",
...
}
vs.
38. Stateful Session API Design w/ Server Push
• Use resource instances for the interaction
model with a long-running query or agent
process
Use when:
• Interaction with a long-running operation,
LLM-backed service, or agent-based
service
• When the client submits a single message
and needs to look for messages as results
are returned
POST /chatSessions
{ ... }
201 Created
Location: /chatSessions/abc123
{
“chatSession": {
"type": ”query",
”sessionId" : "abc123",
”query" : ”What are the nearby airports to Austin, TX?",
“_links”: {
{
“rel”: “messages”,
“href”:”/chatSessions/abc123/messages”
}
}
...
}
GET /chatSessions/abc123/messages
Connection: keep-alive
Content-Type: text/event-stream
200 OK
Content-Type: text/event-stream
event: message
data: { … }
event: message
data: { … }
39. Bi-Directional + Stateful Session API Design
• Use resource instances for the interaction
model with a long-running query or agent
process
• Expands the interaction to support bi-
directional communication
Use when:
• When the client may submit one or more
messages and receive one or more
responses
• Useful for interacting with LLMs that require
training or session content
(e.g., ChatGPT-style)
POST /chatSessions
{ ... }
201 Created
Location: /chatSessions/abc123
{
“chatSession": {
”sessionId" : "abc123",
“_links”: {
{
“rel”: “messages”,
“href”:”/chatSessions/abc123/messages”
}
}
...
}
POST /chatSessions/abc123/messages
Connection: Upgrade
Upgrade: websocket
101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
{”query" : ”What are the nearby airports to Austin, TX?" }
{ … }
{ … }
{ … }
{”query" : ”What about near Fredericksburg, TX?" }
{ … }
40. Those comfortable with
EDA and Async APIs will
have an advantage when
delivering high value APIs
driven by LLMs and AI
Revisiting past messages vs. Receiving new pushed messages
Incoming webhooks for third-party integration
SSE mimics typical HTTP-based styles. SSE is mono-directional (server to client), HTTP protocol with error handling standards. It requires no sub-protocol and is flexible to support a variety of payload formats.
WebSockets are bilateral (you don’t always need bi-direction), not HTTP (some proxy won’t let it go through) “protocol” without standards for error handling. WebSockets are great for real-time and long-lived bi-directional communications. Websockets support text and binary format and often choose a sub-protocol that defines how clients will communicate