5 interesting things you probably shouldn't do with GraphQL

A.K.A. Those are bad practices / antipaterns

If you have high blood pressure and/or care about best practices, leave now!

!

!

On the menu tonight

  1. Function based vs Graph/Circular object
  2. Queries are Async, Mutations are Sync
  3. Parameter chaining / context hoarding
  4. Live resolvers with subscriptions
  5. Dataloaders to share logic/data

Traditional GraphQL resolvers

Function based resolvers

Traditional GraphQL resolvers

Function based resolvers

query {

  authors{

    id

    name

  }

}

{

  id: 0,

  name: 'Arthur',

  tweets: () => getTweets([0,1])

},

{

  id:1,

  name: 'Bob',

  tweets: () => getTweets([2)]

}

Traditional GraphQL resolvers

Function based resolvers

query {

  authors{

    id

    name

    tweets{

      id

      text

  }

}

{

  id: 0,

  name: 'Arthur',

  tweets: () => getTweets([0,1])

},

{

  id:1,

  name: 'Bob',

  tweets: () => getTweets([2)]

}

{

  id: 0,

  text: 'Hello world',

  author: () => getUser(0)

},

{

  id:1,

  text: 'Another one',

  author: () => getUser(1)

}

{

  id: 2,

  text: 'Hello world',

  author: () => getUser(1)

}

GraphQL

Circular Objects

query {

  authors{

    id

    name

}

{

  id: 0,

  name: 'Arthur',

  tweets: [ { id: 0, text:'Hello World', author:{...}},

                  { id: 1, text: 'Another One', author:{...}]

},

{

  id:1,

  name: 'Bob',

  tweets: [ { id: 2, text:'Hello World', author:{...}}]

},

GraphQL

Graph / Circular Objects

query {

  authors{

    id

    name

    tweets{

      id

      text

  }

}

{

  id: 0,

  name: 'Arthur',

  tweets: [ { id: 0, text:'Hello World', author:{...}},

                  { id: 1, text: 'Another One', author:{...}]

},

{

  id:1,

  name: 'Bob',

  tweets: [ { id: 2, text:'Hello World', author:{...}}]

},

GraphQL

Graph / Circular Objects

  • Super fast to resolve deeply nested structures
  • Easy to type / build static objects
  • Less verbose resolvers

     
  • Need to maintain sync between database and memory
  • Most likely need to pull from the database on startup (serverless will kill you)
  • Memory cost money and databases are designed to handle that kind of datafetching
  • Prepare yourself for distributed backend horror stories and out of sync servers

Queries are Async, Mutations are Sync

Queries are Async, Mutations are Sync

  • base for the next trick
  • use (fake) queries and mutations in the same request

 

  • Be prepared to face confused coworkers
  • GraphQL doesn't document itself
  • No frontend libraries will understand you (bye bye Apollo and gqless)
  • "WTF are you doing there?"

Parameter chaining & context hoarding

Parameter chaining & context hoarding

  • Get backend powers in your frontend
  • Cache expensive database queries
  • Reduce the number of roundtrips
     
  • Might fail halfway, your UI needs to prepare for it
  • Must be comfortable with each mutation resolvers, people might not go through your flow if they have a choice.
  • Harder to secure

Live resolvers with subscriptions

Live resolvers with subscriptions

  • Get data ASAP
  • upgrade to websocket your communications
     
  • Required data might be "missing"
  • websockets still not 100% there (gateway timeouts, offline handling, ...)
  • Way more code for your Frontend

Dataloaders to share logic/data

Dataloaders to share logic/data

  • Closest to best practices of all the tips (prevent N+1s database calls)
  • speeds everything up
     
  • Easy to get wrong (mismatch input/return)
  • Do not do Auth/autorization in them
  • More verbose, especially if you want to keep passing the context/parameters down the line

deck

By pookmook

deck

  • 117