Designing GraphQL Schemas

Designing GraphQL Schemas

Shopify has been building GraphQL APIs for over 2 years and we've learned a lot along the way. In this talk I'll reveal some of the fundamental concepts we use to design and build our schemas. We'll be implementing a sample ecommerce feature to demonstrate these concepts and best practices.


Scott Walkinshaw

May 30, 2018


  1. Scott Walkinshaw Designing GraphQL Schemas

  2. Lessons learned from creating and evolving production schemas at Shopify.

  3. We believe these design guidelines work in most cases. They

    may not all work for you.
  4. Imagine you work for a made up ecommerce company

  5. None
  6. Collections Collection Memberships Products

  7. Collection ManualCollection AutomaticCollection

  8. Schema

  9. None
  10. None
  11. None
  12. None
  13. None
  14. Never expose implementation details in your API design. Rule #1

  15. None
  16. It's easier to add schema elements than to remove them.

    Rule #2
  17. None
  18. List-type fields should almost always non-null lists with non-null elements.

    Like lists, boolean fields should almost always non-null. Tips
  19. type Collection { id: ID! rules: [CollectionRule!]! rulesApplyDisjunctively: Bool! products:

    [Product!]! title: String! imageId: ID bodyHtml: String } type CollectionRule { column: String! relation: String! condition: String! }
  20. None
  21. Group closely-related fields together into subobjects. Rule #3

  22. None
  23. None
  24. Always check whether list fields should be paginated or not.

    Rule #4
  25. None
  26. None
  27. Always use object references instead of ID fields. Rule #5

  28. None
  29. None
  30. Choose field names based on what makes sense, not based

    on the implementation or what the field is called in legacy APIs. Rule #6
  31. None
  32. Use custom scalar types when you're exposing something with specific

    semantic value. Rule #7
  33. None
  34. None
  35. Use enums for fields which can only take a specific

    set of values. Rule #8
  36. Business Logic

  37. None
  38. The API should provide business logic, not just data. Complex

    calculations should be done on the server, in one place, not on the client, in many places. Rule #9
  39. None
  40. Provide the raw data too, even when there's business logic

    around it. Rule #10
  41. Mutations

  42. None
  43. • collectionCreate • collectionDelete • collectionAddProducts • collectionRemoveProducts • collectionReorderProducts

    Logical Actions
  44. Write separate mutations for separate logical actions on a resource.

    Rule #11
  45. None
  46. None
  47. Use a payload return type for each mutation. Rule #12

  48. None
  49. Mutations should provide user/business-level errors via a userErrors field on

    the mutation payload. The top-level query errors entry is reserved for client and server-level errors. Rule #13
  50. Most payload fields for a mutation should be nullable. Rule

  51. Thanks!