operational api design anti-patterns (jason harmon)
TRANSCRIPT
Operational API Design
Anti-PatternsJason Harmon @jharmn
@typeform
Head of APIs @Typeform
Leading microservice replatform
Leading developer focused initiatives
Previous API experience:
PayPal/Braintree
uShip
Wayport / AT&T
Jason Harmon
Old blogs at:APIUX.com
Pragmaticapi.com
“API Design Anti-Patterns” talk from last year
https://www.youtube.com/watch?v=lotdj-ry8YA
Design issues don’t always cause operational issues.
Haven’t we already talked about this?
Usability issues Operational issues
HTTP GET instead of POST
Landing
GET /landing200 OK{ “Token”: “abc123”}
User Human
A Form
User Human
Submit
User Human
Submit
User Human
Click “Back” ?
Submit needs to have a landing(to derive “response rate”)POST /submissions (+landing_id in body)
Issue: GET Caches
+ HTTP GET
GET /landing
Caching ProxyOr CDN
Cached responseX
200 OK{ “Token”: “abc123”}
Landings: Better
User Human POST /landing200 OK{ “Token”: “abc123”}
Identification: Unexpected cached API calls from browser/proxy/etc
Solution: Use POSTLive already?
Just add POSTAdd ?cache_buster=[random] to GET
Summary: GET instead of POST
Polling APIs
Polling APIs
Problem Identification:● Large dataset● Expensive queries● Frequently changing data● Lots of clients
Client app
Every 5 minsThousands of
forms
Solution: Webhooks
Client app
Register URL
New data = POST
Still needed for missing data
WHAT IF THIS IS ALREADY HAPPENING!!?!
Client appOptions:● Launch webhooks!● Caching (if possible)● Read-only DB replica● Cheaper query to check for
new data before retrieval
Rigid Hierarchy
Microservices structure: Forms
Issue: Many callsMicroservices
Form Structure + Backend-for-FrontendMicroservices
BFF
AKA● Composition● Orchestration
GraphQL is another potential option
Problem: Client performance in UXN+1 calls (client calls for parent, then calls for
related/child items)Identification:
Data lacking in main resource, usually for UX devs.
Easy to add in live scenarios
Summary: Rigid resource structure
Generic Actions
AKA RPC
Commonly used in controlled state transitions:
POST /forms/:id/publish
{
“comment”: “It’s the right time”
}
What’s an “action”
Perform multiple actions with one endpoint
POST /forms/:id/change-status
{
“action”: “publish”,
“comment”: “My favorite version of this form”
}
Generic “action”
Product Owner- Any performance issues?
Devs
Product owner: - So how many “publish” actions happened?
Devs
TO THE LOGS!
Dear Product Owner. We need to build a new metrics system to answer that question.
- Yours truly, dev team.
PO
Product Owner’s reply:
Cheap visibility is a good thing
Generic ActionsIdentification:
POST /resource/:id/generic-name + {action: process}
Problem: “Protocol tunneling”: Lack of traceability, more work for metrics (vs cheaper HTTP logs method)
Solution: POST /resource/:id/action-name
Already live? ?action=name in optional query parameter
API Design Takeaways
Use cases first, then design.
Design can influence performance.
Structure is good, but be prepared to blur the lines.
Design can put out fires.
Don’t forget the logs.
That’s it!