Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Designing APIs: Less Data is More

Designing APIs: Less Data is More

Often developers design APIs that expose more than is needed - unnecessary fields, redundant relationships, and endpoints that no one asked for.

These kinds of practices later on introduce communication overhead, extra maintenance costs, negative performance impacts, and waste time that could have been spent better otherwise.

We'll walk through how to design minimal APIs that are straight forward to use, and that are exactly what our consumers need!

5f81e2d2889d7642fd84c8b24db7ee17?s=128

DamirSvrtan

April 13, 2021
Tweet

Transcript

  1. Designing APIs Damir Svrtan Less Data is More

  2. Damir Svrtan He/him Senior Software Engineer @ Netflix Twitter: @DamirSvrtan

  3. San Francisco 🇺🇸

  4. Zagreb 🇭🇷

  5. Designing APIs Less Data is More

  6. Avoiding overhead when designing APIs

  7. Bloated overly flexible APIs

  8. What kind of APIs? • HTTP based APIs • REST

    APIs, JSON APIs, GraphQL etc
  9. API technology agnostic Applicable for all kinds of APIs

  10. Blogging Platform

  11. Blogging Platform: • Authors can release posts • Posts can

    have comments
  12. Two principles for building APIs • Designing the minimal API

    surface • Designing from Strict to Loose
  13. 1st Principal Design the minimal API surface

  14. Bloated API surface: - redundant fields - redundant relationships -

    redundant input fields
  15. Don’t Expose Redundant Fields

  16. Requirement: “Show the author of the blogpost”

  17. CREATE TABLE authors ( id first_name last_name email avatar_url );

  18. None
  19. Friendly API developer: “Let’s expose the email, someone might find

    it useful in the future”
  20. type Author { id firstName lastName avatarUrl email }

  21. 6 months later: Privacy reasons: stop exposing the email

  22. ..deprecation cycle..

  23. ..extreme amounts of communication..

  24. ..breaking clients..

  25. ..extreme amounts redundant cycles..

  26. Don’t Expose Redundant Relationships

  27. Requirement: “Indicate whether a post was reviewed”

  28. type Post { title:String body:String }

  29. type Post { title:String body:String reviewed:Boolean }

  30. Friendly API developer: “Let’s expose the reviewer for future use

    cases”
  31. type Post { title:String text:String reviewed:Boolean reviewer: Reviewer }

  32. Development costs are growing; - batch/eager loading - testing -

    performance impacts
  33. type Post { title:String text:String reviewed:Boolean reviewers: [Reviewer] } type

    Post { title:String text:String reviewed:Boolean reviewer: Reviewer }
  34. ..deprecation cycle..

  35. ..breaking clients..

  36. Delaying Decisions Adding later when we have more knowledge is

    better
  37. It’s easier to add in the future than to remove

  38. Don’t Expose Redundant Input Fields

  39. Requirement: “Readers need to be able to create and update

    comments”
  40. input CreateComment { postId: ID body: String }

  41. The friendly API developer: “Let’s have parity between inputs”

  42. input UpdateComment { id: ID postId: ID body: String }

  43. The blogging platform doesn’t support comment transitions from one post

    to another
  44. input UpdateComment { id: ID postId: ID body: String }

  45. Avoid anemic data modeling

  46. None
  47. Ambiguity deteriorates Developer Experience

  48. YAGNI You Ain’t Gonna Need It

  49. 2nd Principal Strict to Loose

  50. - Avoid extra flexibility - Breaks First!

  51. Avoid extra flexibility

  52. Requirement: “The users need to be able to see comments

    on a post”
  53. comments(postId: ID @required)

  54. The friendly API developer: “Our clients might want to fetch

    all comments in the future”
  55. comments(postId: ID @optional)

  56. Unneeded application logic

  57. If postId.present? … else … end

  58. More code = More maintenance

  59. More code = More tests

  60. On inputs, it’s easy to go from required to optional,

    not the other way around
  61. Strict to Loose gives you more control

  62. Loose to Strict is a breaking change

  63. Breaks First!

  64. Requirement: “Ability to fetch comments for a post”

  65. The friendly API developer: “Let’s just give them an array

    of comments, we don’t need pagination!”
  66. The friendly API developer: “Let’s just give them an array

    of comments, we don’t need pagination yet!”
  67. comments(postId: ID): [Comment]

  68. The friendly API developer: “We won’t have more than 5

    comments per post!”
  69. 6 months after: “There’s posts with 100’s of comments”

  70. Developer: “Let’s add pagination”

  71. comments(postId: ID): PaginatedComments

  72. Work is done, let’s go home!

  73. comments(postId: 1, first: 1000)

  74. The Friendly API Developer didn’t add limits to pagination

  75. Add pagination limitations from the beginning

  76. Error Message: Requesting 1000 records exceeds the `first` limit of

    100 records.
  77. Super hard to add retroactively, but super easy to adjust

    in the future.
  78. How to avoid these overheads?

  79. Adopt Schema First Design

  80. Talk to your clients

  81. Be responsive to your clients requests

  82. There’s always exceptions

  83. Platform APIs

  84. Constraints due to release cycles

  85. Conclusion

  86. Redundant work slows down progress on important features

  87. “The road to hell is paved with good intentions”

  88. Thank you! 👋 Twitter: @DamirSvrtan