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

GraphQL Schema Design @ Scale

GraphQL Schema Design @ Scale

GraphQL Schema Design and Tooling @ GitHub

Marc-Andre Giroux

November 07, 2018
Tweet

More Decks by Marc-Andre Giroux

Other Decks in Programming

Transcript

  1. Marc-Andre Giroux
    @___xuorig___
    GraphQL Summit - Nov 7th 2018
    GraphQL
    Schema Design
    @ scale

    View Slide

  2. about { xuorig }
    • Montreal, Canada ☃
    • My 3rd GraphQL Summit
    • I work at GitHub!
    2

    View Slide

  3. 3

    View Slide

  4. GraphQL @ GitHub
    • 200+ engineers working on GraphQL schema
    • Teams have to move quickly
    • Public and Internal Schema + Enterprise.
    4

    View Slide

  5. GraphQL @ GitHub: Challenges
    • Keeping a high quality public API across many teams and use
    cases.
    • Small API team
    • Best practices are still emerging, lots and lots of PR reviews
    to go through, and many new use cases appearing every
    week.
    5

    View Slide

  6. Why GraphQL?
    6

    View Slide

  7. A type system to
    express possibilities
    7

    View Slide

  8. Declarative: Clients select what
    they need and nothing more
    8

    View Slide

  9. Why do we design?
    9

    View Slide

  10. Why we design
    • Build APIs that are easier to evolve: Best way to mitigate
    breaking changes we don't know about yet
    • Build APIs that are easier to reason about
    10

    View Slide

  11. GraphQL Schema Design
    11

    View Slide

  12. Misconceptions
    12

    View Slide

  13. In a complex application GraphQL is
    rarely an interface to your database
    13

    View Slide

  14. Your GraphQL Schema does not need to match your
    existing REST resources
    14

    View Slide

  15. It also does not have to be a 1:1
    mapping to your UI
    15

    View Slide

  16. The real power of GraphQL
    16

    View Slide

  17. GraphQL lets us model an interface to our
    core domain
    17

    View Slide

  18. For a lot of us, it is often an opportunity to
    design from scratch (and maybe get it right this time? )
    18

    View Slide

  19. To let go of our coupling to our database
    schema, our REST resources or our UI
    19

    View Slide

  20. Major to a well designed GraphQL API
    20

    View Slide

  21. 21

    View Slide

  22. • Be an expert at your domain, understand the ins and out
    21

    View Slide

  23. • Be an expert at your domain, understand the ins and out
    • Be an expert at GraphQL specific design
    21

    View Slide

  24. But there's one problem...
    22

    View Slide

  25. 23

    View Slide

  26. Rarely the same people!
    24

    View Slide

  27. API First
    25

    View Slide

  28. Built by the product team
    26

    View Slide

  29. Helped by the API team! ❤
    27

    View Slide

  30. Design Tips
    28

    View Slide

  31. Design Tips
    29

    View Slide

  32. Guiding Principles
    30

    View Slide

  33. Guiding Principles
    31
    (and some cool tools)

    View Slide

  34. Design for behaviors or use cases over data
    32

    View Slide

  35. Anemic GraphQL ™
    33

    View Slide

  36. 34

    View Slide

  37. 35

    View Slide

  38. 36

    View Slide

  39. 37

    View Slide

  40. 38

    View Slide

  41. 39

    View Slide

  42. 40

    View Slide

  43. Atomicity vs Granularity
    41

    View Slide

  44. 42

    View Slide

  45. Let's go back a few years...
    43

    View Slide

  46. Problem: Multiple clients with very different needs
    44

    View Slide

  47. 45
    Backend For Frontend Pattern
    http://philcalcado.com/2015/09/18/the_back_end_for_front_end_pattern_bff.html

    View Slide

  48. 46
    Netflix: Client Optimized API Adapters
    https://medium.com/netflix-techblog/embracing-the-differences-inside-the-netflix-api-redesign

    View Slide

  49. 47

    View Slide

  50. In a way... GraphQL is our BFF / Client Adapter
    48

    View Slide

  51. Declarative & Client Centric
    49

    View Slide

  52. Select *
    50

    View Slide

  53. Select *
    51

    View Slide

  54. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    52

    View Slide

  55. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    53

    View Slide

  56. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    54

    View Slide

  57. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    55

    View Slide

  58. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    56

    View Slide

  59. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    57

    View Slide

  60. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    58

    View Slide

  61. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    59

    View Slide

  62. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    60

    View Slide

  63. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    61

    View Slide

  64. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    62

    View Slide

  65. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    63

    View Slide

  66. type User {
    billingInfo: BillingInfo!
    email: String!
    login: String!
    fullName: String!
    recentIssues: [Issue!]!
    repositories: [Repository!]!
    reviewRequests: [ReviewRequest!]!
    isOwner(repositoryID: ID!): Boolean!
    starredRepositories: [Repository!]!
    }
    64

    View Slide

  67. We shouldn't be afraid of adding use cases or client
    specific fields if it fits a domain use case
    65

    View Slide

  68. Stay away from trying to build a "One Size Fits All" API
    66

    View Slide

  69. and embrace the different use cases and clients
    67

    View Slide

  70. Prefer highly optimized fields over generic/smart fields
    68

    View Slide

  71. 69

    View Slide

  72. 70

    View Slide

  73. Design @ Scale: GitHub's Tooling
    71

    View Slide

  74. 72
    Checked-in SDL

    View Slide

  75. 73
    Checked-in SDL

    View Slide

  76. 74

    View Slide

  77. 75

    View Slide

  78. 76

    View Slide

  79. 77

    View Slide

  80. 78
    )
    GraphQL Doctor

    View Slide

  81. 79

    View Slide

  82. 80

    View Slide

  83. 81

    View Slide

  84. Sometimes we make mistakes
    82

    View Slide

  85. 83

    View Slide

  86. 84

    View Slide

  87. 85

    View Slide

  88. 86

    View Slide

  89. 87

    View Slide

  90. 88

    View Slide

  91. 89
    Fake it 'till you make it!

    View Slide

  92. 90

    View Slide

  93. Making the change
    91

    View Slide

  94. Who is using the field?
    92

    View Slide

  95. How much is it being used?
    93

    View Slide

  96. No Select *: We know exactly how our schema is used!
    94

    View Slide

  97. 95
    query {
    viewer {
    login
    email
    }
    }

    View Slide

  98. 95
    query {
    viewer {
    login
    email
    }
    }
    GitHub API

    View Slide

  99. 96
    query {
    viewer {
    login
    email
    }
    }
    GitHub API

    View Slide

  100. 96
    query {
    viewer {
    login
    email
    }
    }
    GitHub API
    GraphQL Query
    Analytics

    View Slide

  101. 97
    query {
    viewer {
    login
    email
    }
    }
    GraphQL Query
    Analytics
    Type: Query
    Field: viewer
    App: xxx
    Type: User
    Field: login
    App: xxx
    ...

    View Slide

  102. 98
    Type: Query
    Field: viewer
    App: xxx
    Type: User
    Field: login
    App: xxx
    ...

    View Slide

  103. 99
    Type: Query
    Field: viewer
    App: xxx
    Type: User
    Field: login
    App: xxx
    ...

    View Slide

  104. 100

    View Slide

  105. 101

    View Slide

  106. GraphQL Schema Design @ Scale
    102

    View Slide

  107. Talk to, (or become) domain experts
    103

    View Slide

  108. Think Domain over Data
    104

    View Slide

  109. Sometimes it's not about "One Size Fits All"
    105

    View Slide

  110. Use the schema to build (or use) great tools!
    106

    View Slide

  111. Marc-Andre Giroux
    @___xuorig___
    GraphQL Summit - Nov 7th 2018
    Thank You!

    View Slide