scalabay - api design antipatterns
Post on 19-Oct-2014
246 views
DESCRIPTION
Slides from my talk on API Design Patterns at ScalaBay Meetup at Netflix on 09/09/2014. http://www.meetup.com/Scala-Bay/events/195982742/TRANSCRIPT
![Page 1: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/1.jpg)
API An&pa)erns …iden&fying, and avoiding them
Manish Pandit @lobster1234
![Page 2: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/2.jpg)
Manish Pandit @lobster1234
mpandit at neAlix dot com
linkedin.com/in/mpandit slideshare.net/lobster1234
@lobster1234
![Page 3: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/3.jpg)
APIs
A means for soGware to interact with other soGware.
@lobster1234
![Page 4: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/4.jpg)
@lobster1234
![Page 5: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/5.jpg)
@lobster1234
Image Credit: h)p://en.wikipedia.org/wiki/Internet_of_Things
![Page 6: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/6.jpg)
@lobster1234
![Page 7: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/7.jpg)
REST API
REST is not a standard, but an architecture
@lobster1234
![Page 8: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/8.jpg)
REST API
REST is not a standard, but an architecture, which uses HTTP as a model for all interac.ons.
If HTTP is a standard, REST is a conven&on.
@lobster1234
![Page 9: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/9.jpg)
@lobster1234
![Page 10: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/10.jpg)
REST API
Noun è Resource, or the En&ty
Verb è Ac&on
+ Iden.fier
@lobster1234
![Page 11: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/11.jpg)
Image: h)p://www.educa&on.com/study-‐help/ar&cle/nouns/
@lobster1234
![Page 12: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/12.jpg)
Protocol
May or may not be standard
@lobster1234
![Page 13: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/13.jpg)
Protocol
May or may not be standard Indicates an agreement between the par&es
@lobster1234
![Page 14: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/14.jpg)
@lobster1234
![Page 15: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/15.jpg)
Payload
Format (XML, JSON, Custom Text, Binary..)
Transport (HTTP, Binary over sockets, FTP..)
@lobster1234
![Page 16: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/16.jpg)
@lobster1234
![Page 17: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/17.jpg)
h)p://www.neAlix.com/header/neAlix_logo.gif Or, reques.ng a resource from the server by
giving its path using a protocol.
@lobster1234
![Page 18: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/18.jpg)
Every request deserves a response.
@lobster1234
![Page 19: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/19.jpg)
Headers describe the response
@lobster1234
![Page 20: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/20.jpg)
Headers describe the response
Status Code indicates the success/failure
@lobster1234
![Page 21: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/21.jpg)
Headers describe the response
Status Code indicates the success/failure
Body contains the actual payload
@lobster1234
![Page 22: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/22.jpg)
Tell the server what to do via ac.ons
@lobster1234
![Page 23: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/23.jpg)
Ac&ons are HTTP methods, which map nicely to
(most of) the business interac&ons
@lobster1234
![Page 24: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/24.jpg)
Create – POST Read – GET
Update – PUT (or PATCH) Delete -‐ DELETE
HEAD, OPTIONS, TRACE, CONNECT
@lobster1234
![Page 25: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/25.jpg)
Pa)erns
@lobster1234
![Page 26: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/26.jpg)
Pa)erns
Pa)erns are re-‐usable solu&ons to commonly occurring problems.
@lobster1234
![Page 27: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/27.jpg)
Common Scenarios
Gebng data from the server
@lobster1234
![Page 28: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/28.jpg)
Common Scenarios
Gebng data from the server
Sending data to the server
@lobster1234
![Page 29: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/29.jpg)
An&pa)erns
An&pa)erns are re-‐usable solu&ons to commonly occurring problems, that look great on the surface, but
really aren’t.
@lobster1234
![Page 30: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/30.jpg)
Request An&pa)erns
@lobster1234
![Page 31: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/31.jpg)
Over-‐using Query Strings
@lobster1234
![Page 32: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/32.jpg)
/pets?name=scruffy vs.
/pets/name/scruffy
@lobster1234
![Page 33: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/33.jpg)
/pets?name=scruffy&zip=94568 vs.
/pets/name/scruffy/loca&on/zip/94568
@lobster1234
![Page 34: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/34.jpg)
Avoid query strings for resource iden&fica&on But use them for request metadata *
*Except for search
@lobster1234
![Page 35: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/35.jpg)
Pagina&on Filtering Sor&ng
..
@lobster1234
![Page 36: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/36.jpg)
@lobster1234
![Page 37: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/37.jpg)
Query Strings
h)p://some.api.com/movies?start=0&count=10&sortBy=name&fields=name,cast,releaseDate
@lobster1234
![Page 38: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/38.jpg)
Allowing clients to scrape the data via your APIs
@lobster1234
![Page 39: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/39.jpg)
@lobster1234
![Page 40: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/40.jpg)
Think batch jobs reques&ng the catalog nightly!
@lobster1234
![Page 41: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/41.jpg)
Request metadata to the rescue?
@lobster1234
![Page 42: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/42.jpg)
….how about a ?since=1d
…or ?since=UTC
@lobster1234
![Page 43: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/43.jpg)
Method An&pa)erns
@lobster1234
![Page 44: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/44.jpg)
Using Query Strings to overload verbs
@lobster1234
![Page 45: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/45.jpg)
/pets?perform=update&name=scruffy&id=24
@lobster1234
![Page 46: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/46.jpg)
Use the appropriate HTTP Method to represent your ac&on
@lobster1234
![Page 47: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/47.jpg)
Using POST for all writes
@lobster1234
![Page 48: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/48.jpg)
GET to retrieve, or search POST to create, or upsert
PUT to update (or be)er yet, PATCH) DELETE to delete
@lobster1234
![Page 49: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/49.jpg)
Using HTTP PUT or POST to set a value to null
@lobster1234
![Page 50: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/50.jpg)
Updates vs. Deletes
Everything works when there is data, but what
when there is no data..?
@lobster1234
![Page 51: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/51.jpg)
Use HTTP DELETE to set a value to null
Remember, we have a path to not just the resource, but also it’s
a)ributes
@lobster1234
![Page 52: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/52.jpg)
DELETE /pets/<id>/collartag
@lobster1234
![Page 53: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/53.jpg)
Response An&pa)erns
@lobster1234
![Page 54: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/54.jpg)
Always returning HTTP 200
@lobster1234
![Page 55: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/55.jpg)
@lobster1234
![Page 56: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/56.jpg)
HTTP 200 OK
{ “success” : false }
@lobster1234
![Page 57: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/57.jpg)
HTTP 200 OK
{ “error” : ”Person jdoe not found” }
@lobster1234
![Page 58: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/58.jpg)
2xx for success 3xx for redirects/caching
4xx for request/client errors 5xx for server errors
@lobster1234
![Page 59: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/59.jpg)
Some Useful (and not so common) Codes
Return aGer a delete -‐ 204 Failed database constraint -‐ 409 Method not supported -‐ 405
Trying to ask for too much data -‐ 413 Valida&on Failure -‐ 418
@lobster1234
![Page 60: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/60.jpg)
Always returning a 401 for auth failures
![Page 61: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/61.jpg)
@lobster1234
![Page 62: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/62.jpg)
Auth
Use HTTP 401 Unauthorized to indicate that the client needs to authen&cate
@lobster1234
![Page 63: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/63.jpg)
Auth
Use HTTP 403 Forbidden to indicate that the client’s creden&als do not allow access to the
requested resource
@lobster1234
![Page 64: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/64.jpg)
401 vs 403
401 = Come back with a key
403 = Your key does not work for this lock.
@lobster1234
![Page 65: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/65.jpg)
Processing requests synchronously, even &me
intensive ones
@lobster1234
![Page 66: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/66.jpg)
Async the opera&on, and return HTTP 202 – Accepted
@lobster1234
![Page 67: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/67.jpg)
@lobster1234
![Page 68: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/68.jpg)
Async opera&on’s response should help the
caller.
{“statusUrl”: <some URL>}
@lobster1234
![Page 69: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/69.jpg)
Organiza&onal An&pa)erns
@lobster1234
![Page 70: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/70.jpg)
Not differen&a&ng between en..es and instances
@lobster1234
![Page 71: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/71.jpg)
/pets?type=dog&name=big vs
/pets/dogs/name/big
@lobster1234
![Page 72: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/72.jpg)
Namespace your resources in a collec&on Use paths and iden&fiers to traverse
@lobster1234
![Page 73: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/73.jpg)
Using id in the resource iden&fica&on path
@lobster1234
![Page 74: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/74.jpg)
/pets/id/1234
vs
/pets/1234
@lobster1234
![Page 75: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/75.jpg)
Use all other a)ributes in the path, except the
id. id is implied
@lobster1234
![Page 76: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/76.jpg)
@lobster1234
Resources in an island
![Page 77: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/77.jpg)
@lobster1234
![Page 78: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/78.jpg)
Every en&ty or a resource is &ed to others.
@lobster1234
![Page 79: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/79.jpg)
Every en&ty or a resource is &ed to others.
And you’re stuck guessing the connec&ons!
@lobster1234
![Page 80: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/80.jpg)
@lobster1234
We’ll just return the IDs!
![Page 81: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/81.jpg)
HATEOAS
(or something similar)
@lobster1234
![Page 82: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/82.jpg)
Read code to figure out the resources and
a)ributes.
@lobster1234
![Page 83: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/83.jpg)
@lobster1234
![Page 84: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/84.jpg)
Use Meta pages for resource descrip&on /resource/meta /collec&on/meta
@lobster1234
![Page 85: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/85.jpg)
APIs are not discoverable
@lobster1234
![Page 86: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/86.jpg)
Consider a documenta&on generator like Swagger, IODocs
@lobster1234
![Page 87: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/87.jpg)
Relying on cookies for authen&ca&on
@lobster1234
![Page 88: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/88.jpg)
@lobster1234
![Page 89: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/89.jpg)
Accept cookies as a fallback, but prefer a query
parameter or HTTP request header.
@lobster1234
![Page 90: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/90.jpg)
Storing state on the server nodes
@lobster1234
![Page 91: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/91.jpg)
Stateless == Simple
@lobster1234
![Page 92: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/92.jpg)
Requests either modify the state of a resource, or read it.
All requests to the cluster see the same state of the resource
@lobster1234
![Page 93: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/93.jpg)
Avoid state as much as possible. Maintain the state in the database.
If you need to store transient state on the server, it’s a code (or architecture) smell.
@lobster1234
![Page 94: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/94.jpg)
Versioning Using 301s to redirect/re&re APIs
Caching
Using HTTP headers correctly Caching response bodies
@lobster1234
![Page 95: Scalabay - API Design Antipatterns](https://reader034.vdocuments.mx/reader034/viewer/2022042515/5444870cb1af9f680a8b495b/html5/thumbnails/95.jpg)
@lobster1234
Fin