Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

3

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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

Slide 6

Slide 6 text

Why GraphQL? 6

Slide 7

Slide 7 text

A type system to express possibilities 7

Slide 8

Slide 8 text

Declarative: Clients select what they need and nothing more 8

Slide 9

Slide 9 text

Why do we design? 9

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

GraphQL Schema Design 11

Slide 12

Slide 12 text

Misconceptions 12

Slide 13

Slide 13 text

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

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

The real power of GraphQL 16

Slide 17

Slide 17 text

GraphQL lets us model an interface to our core domain 17

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

Major to a well designed GraphQL API 20

Slide 21

Slide 21 text

21

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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

Slide 24

Slide 24 text

But there's one problem... 22

Slide 25

Slide 25 text

23

Slide 26

Slide 26 text

Rarely the same people! 24

Slide 27

Slide 27 text

API First 25

Slide 28

Slide 28 text

Built by the product team 26

Slide 29

Slide 29 text

Helped by the API team! ❤ 27

Slide 30

Slide 30 text

Design Tips 28

Slide 31

Slide 31 text

Design Tips 29

Slide 32

Slide 32 text

Guiding Principles 30

Slide 33

Slide 33 text

Guiding Principles 31 (and some cool tools)

Slide 34

Slide 34 text

Design for behaviors or use cases over data 32

Slide 35

Slide 35 text

Anemic GraphQL ™ 33

Slide 36

Slide 36 text

34

Slide 37

Slide 37 text

35

Slide 38

Slide 38 text

36

Slide 39

Slide 39 text

37

Slide 40

Slide 40 text

38

Slide 41

Slide 41 text

39

Slide 42

Slide 42 text

40

Slide 43

Slide 43 text

Atomicity vs Granularity 41

Slide 44

Slide 44 text

42

Slide 45

Slide 45 text

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

Slide 46

Slide 46 text

Problem: Multiple clients with very different needs 44

Slide 47

Slide 47 text

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

Slide 48

Slide 48 text

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

Slide 49

Slide 49 text

47

Slide 50

Slide 50 text

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

Slide 51

Slide 51 text

Declarative & Client Centric 49

Slide 52

Slide 52 text

Select * 50

Slide 53

Slide 53 text

Select * 51

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

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

Slide 56

Slide 56 text

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

Slide 57

Slide 57 text

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

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

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

Slide 61

Slide 61 text

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

Slide 62

Slide 62 text

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

Slide 63

Slide 63 text

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

Slide 64

Slide 64 text

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

Slide 65

Slide 65 text

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

Slide 66

Slide 66 text

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

Slide 67

Slide 67 text

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

Slide 68

Slide 68 text

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

Slide 69

Slide 69 text

and embrace the different use cases and clients 67

Slide 70

Slide 70 text

Prefer highly optimized fields over generic/smart fields 68

Slide 71

Slide 71 text

69

Slide 72

Slide 72 text

70

Slide 73

Slide 73 text

Design @ Scale: GitHub's Tooling 71

Slide 74

Slide 74 text

72 Checked-in SDL

Slide 75

Slide 75 text

73 Checked-in SDL

Slide 76

Slide 76 text

74

Slide 77

Slide 77 text

75

Slide 78

Slide 78 text

76

Slide 79

Slide 79 text

77

Slide 80

Slide 80 text

78 ) GraphQL Doctor

Slide 81

Slide 81 text

79

Slide 82

Slide 82 text

80

Slide 83

Slide 83 text

81

Slide 84

Slide 84 text

Sometimes we make mistakes 82

Slide 85

Slide 85 text

83

Slide 86

Slide 86 text

84

Slide 87

Slide 87 text

85

Slide 88

Slide 88 text

86

Slide 89

Slide 89 text

87

Slide 90

Slide 90 text

88

Slide 91

Slide 91 text

89 Fake it 'till you make it!

Slide 92

Slide 92 text

90

Slide 93

Slide 93 text

Making the change 91

Slide 94

Slide 94 text

Who is using the field? 92

Slide 95

Slide 95 text

How much is it being used? 93

Slide 96

Slide 96 text

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

Slide 97

Slide 97 text

95 query { viewer { login email } }

Slide 98

Slide 98 text

95 query { viewer { login email } } GitHub API

Slide 99

Slide 99 text

96 query { viewer { login email } } GitHub API

Slide 100

Slide 100 text

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

Slide 101

Slide 101 text

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

Slide 102

Slide 102 text

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

Slide 103

Slide 103 text

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

Slide 104

Slide 104 text

100

Slide 105

Slide 105 text

101

Slide 106

Slide 106 text

GraphQL Schema Design @ Scale 102

Slide 107

Slide 107 text

Talk to, (or become) domain experts 103

Slide 108

Slide 108 text

Think Domain over Data 104

Slide 109

Slide 109 text

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

Slide 110

Slide 110 text

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

Slide 111

Slide 111 text

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