Talks

GraphQL on Rails

EuRuKo 2016

00:00:05.050 okay so we're back and
00:00:08.830 we'll continue with our next speaker
00:00:11.620 that will be mark and razor ooh he comes
00:00:15.320 all the way from Canada
00:00:17.750 he's from Shopify and he really is into
00:00:20.930 graph QL rails relay and also he likes
00:00:24.980 to lift barbells over his head just for
00:00:27.860 fun so welcome mark Andre drew
00:00:38.890 hey everyone yeah my name is McConaughey
00:00:42.859 and today we're gonna talk a little bit
00:00:44.839 about graph QL so who's heard about
00:00:47.449 graph QL here
00:00:48.789 so a lot of people who actually uses
00:00:51.769 graph QL
00:00:53.050 okay so a bit less
00:00:55.929 yes I'm really happy to be here in Sofia
00:00:59.479 for a couple of days yesterday I tried
00:01:01.609 Rakiya it was so good if you haven't
00:01:05.000 tried it yet do it I'm suspect I might
00:01:08.000 have a few more tonight after the talks
00:01:11.259 and yeah as you heard I'm come from the
00:01:14.390 cold Montreal Canada
00:01:16.299 and I work at Shopify where I help
00:01:19.280 basically help people sell things on the
00:01:21.350 Internet
00:01:22.960 so today we're gonna talk about graph QL
00:01:27.039 but before we start doing that we're
00:01:30.560 gonna start telling a little story of
00:01:32.960 how we currently fetch data from our
00:01:36.320 client apps and how he structures our
00:01:38.180 api's generally so let's start with a
00:01:41.719 simple UI component and eggs of mine
00:01:44.740 what data we need and how we're gonna
00:01:48.079 fetch it and I've chosen the github cart
00:01:52.810 component here and yeah let's take a
00:01:56.329 look at what we need here
00:01:59.469 we might have a card component here and
00:02:02.090 we might need a card resource for it
00:02:03.939 inside as you see we have products we
00:02:06.710 might need a product resource - and we
00:02:09.770 might decide to have a product image
00:02:11.090 nested in that - so generally how we're
00:02:15.530 gonna fetch this right
00:02:17.069 we might start by using reusable
00:02:18.540 endpoints or a typical rest architecture
00:02:21.480 right and how would that go so in a
00:02:25.290 typical rest architecture will have
00:02:27.540 resources and these resources might
00:02:30.150 expose links hyperlinks to other
00:02:33.120 resources and by following these links
00:02:35.760 we're gonna change States from let's say
00:02:38.069 my card resource to the product resource
00:02:40.790 so we might start by getting our card
00:02:43.769 and that card resource it's gonna return
00:02:47.189 us maybe a few eight rafts towards the
00:02:51.150 products so we're gonna fetch those and
00:02:53.010 these product resources might point us
00:02:55.739 towards the product images and we're
00:02:57.780 gonna fetch us two so that provides us
00:03:01.079 some advantages but there's also
00:03:03.000 something a little annoying with this
00:03:04.739 especially on mobile and slow networks
00:03:07.650 and is that way too many round points
00:03:10.349 round trips sorry
00:03:12.389 expect like imagine on mobile having I
00:03:14.790 think we had seven round trips there
00:03:16.169 it's kind of annoying so we try to find
00:03:19.859 a solution to this right and
00:03:21.680 sometimes we have something like this
00:03:23.549 query param where we can tell give me
00:03:27.479 the card but also expand that resource
00:03:29.970 and provide me with the products
00:03:31.650 resource too so that works but what
00:03:34.379 about deeper nesting and what if I want
00:03:37.259 to select only some fields of these
00:03:38.879 products so maybe you're gonna do
00:03:41.579 another type of query param and be like
00:03:44.729 oh I wonder products but only the name
00:03:46.620 description' in price that works too
00:03:49.970 I've seen many things working by the way
00:03:53.400 many query parameter always different
00:03:55.500 and we kind of have to reinvent the
00:03:56.939 wheel every time and I've yet to see
00:04:00.000 like nice and pretty solution to this so
00:04:04.019 we might be tempted to use something
00:04:05.489 else instead such as custom endpoints so
00:04:08.989 imagine I want a cart
00:04:11.629 with specific requirements and instead
00:04:14.879 of using rest and having full resources
00:04:17.219 returned to me I'm just gonna build my
00:04:19.199 own endpoint and it's going to return
00:04:21.000 everything I need pretty easy right
00:04:23.180 we're done like our appliance app is
00:04:26.460 perfect but as you might expect things
00:04:29.969 can get a little more applicated we
00:04:31.930 might have a card version to a
00:04:33.960 completely different view of the card in
00:04:36.070 our app and we're gonna build a custom
00:04:38.050 endpoint for that too
00:04:39.450 we might build another custom endpoint
00:04:42.070 for the cases when we only want products
00:04:44.980 and images but nothing else and
00:04:47.070 things can get out of end
00:04:52.170 it's a little annoying right
00:04:54.540 so what hands up happening is that every
00:04:57.460 time our client updates of views creates
00:05:00.730 a new view a new view version or just
00:05:04.990 the model changes itself our server
00:05:07.270 needs to either update in points or even
00:05:10.030 worse create new endpoints specific for
00:05:12.100 these changes
00:05:13.350 and that because we have this if we come
00:05:16.360 back to the rest or like reusable
00:05:18.070 endpoints method we have a specific
00:05:20.470 relation with between the client and
00:05:22.210 server right our clients like yo give me
00:05:24.490 the resource with ID ABC and a server
00:05:26.980 just responds here's that resource with
00:05:29.260 ID ABC but what happens when
00:05:32.460 you have a second version the server
00:05:35.770 needs to responds with that version 2 so
00:05:38.170 the server becomes responsible of the
00:05:40.660 shape of the data the DES client wants
00:05:44.110 so when views changes the model changed
00:05:47.830 too
00:05:49.260 so imagine version 3 is the same every
00:05:52.840 time our view changes our endpoint
00:05:54.880 changes and a Marla changes and we end
00:05:57.430 up realizing that our views and models
00:05:59.050 are pretty coupled and this is where
00:06:02.350 graph QL comes in what graph QL you can
00:06:05.980 finally talk about it but actually let's
00:06:08.260 start by saying what graph girl is not
00:06:10.740 so graph girl is not a database
00:06:13.440 it's not some special kind of graph
00:06:16.030 database either it's not a library right
00:06:19.240 you can't just install graph QL and
00:06:21.130 solve all your problems it's also not
00:06:23.650 language specific
00:06:25.169 so what is it
00:06:27.190 so graph QL is a simple query language
00:06:29.410 that allows us to fetch data shapes
00:06:32.140 instead of resources by specifying
00:06:34.750 exactly what we require but it's also a
00:06:38.230 server spec aspect that explains how a
00:06:41.380 server
00:06:43.000 Laxus parses and execute that query
00:06:47.940 so this is a bit of my hello world
00:06:50.770 example here this query here is
00:06:53.949 basically fetching my shop and its name
00:06:57.550 so on the name of my shop and what we
00:07:00.940 have here
00:07:02.669 we have selection sets right the
00:07:05.110 brackets here and these tell graph QL I
00:07:08.680 want to select these fields on that
00:07:11.650 object so it's very simple
00:07:14.940 so when we send that query to a
00:07:17.409 graphical server what send-ups happening
00:07:19.810 is uh it's laxed it's parsed it's
00:07:22.509 validated and finally executed and as
00:07:25.810 you can see this query language is a bit
00:07:28.960 similar to jason but removing the values
00:07:31.870 and what we get in return is actually
00:07:34.720 jason so it's pretty cool our query
00:07:37.810 shape matches our response shape almost
00:07:41.080 one-to-one
00:07:43.050 so here we have name on my shop we
00:07:47.380 understand pretty easily that name is a
00:07:49.300 field on my shop but what is my shop
00:07:51.250 here
00:07:53.729 so it's not some special field or some
00:07:58.150 graphical magic here is that graphic
00:08:00.639 your
00:08:01.259 needs you to define entry points into
00:08:04.180 the graph
00:08:05.130 so for example this query would be
00:08:07.960 equivalent in graph QL if you defined
00:08:09.969 both on the route of graph you are here
00:08:13.930 shop with ID one would be simply the
00:08:16.150 programmatic way of getting my shop but
00:08:18.819 both are valid so in that example we
00:08:22.060 would have that defined on the route of
00:08:23.830 our graph QL schema shop taking an ID
00:08:27.009 argument and my shop and we discover
00:08:30.550 here a new feature of graph PL right we
00:08:32.380 have variables and
00:08:34.050 variables can be applied on fields and
00:08:37.270 you can kind of think of fields as a
00:08:39.250 simple function that takes arguments and
00:08:41.860 returns value
00:08:43.680 let's take a more complicated example
00:08:46.380 here not only we have name on the shop
00:08:49.000 we have its location and products and
00:08:51.779 location and products are not exactly
00:08:54.370 like name right name is a scalar field
00:08:56.350 which returns like simply a string for
00:08:58.570 example but location and products here
00:09:00.850 are complex fields we call them object
00:09:03.640 types and we can query other fields on
00:09:07.630 these object types
00:09:09.090 so you can probably guess what the
00:09:11.350 response is going to look like right
00:09:12.250 it's a little bit like our previous
00:09:14.680 example it matches the shape of our
00:09:16.780 query but it filled that with the actual
00:09:19.150 values
00:09:20.220 and all that's possible like how could a
00:09:24.310 graphical server know that my query here
00:09:26.980 was valid and that it could respond to
00:09:29.800 me and that's possible because of the
00:09:32.650 type system at the core of graph QL is a
00:09:36.010 really powerful static type system that
00:09:39.040 allows you to define exactly what's
00:09:41.470 possible
00:09:42.600 so let's walk through that query and see
00:09:45.940 how the type system applies as I talked
00:09:49.330 about earlier my shop is on the root of
00:09:52.210 our schema and we have that type defined
00:09:55.060 so on a query route we could fetch my
00:09:58.450 shop or we could fit shop with an ID
00:10:01.410 that type would that return the name
00:10:04.480 location and products of the shop and we
00:10:07.030 know that because there's a type
00:10:08.170 attached to it and you can imagine how
00:10:11.740 the query goes it's the same location
00:10:13.840 returned us a location type or address
00:10:16.450 type actually with the city and address
00:10:18.280 and products they return as a product
00:10:20.560 type with name in price
00:10:23.250 so if I take this query does it look
00:10:26.170 valid to you obviously we know it's not
00:10:28.720 valid because it doesn't make sense to
00:10:30.160 have a Yolo field on my shop but the
00:10:33.640 type system knows that too and on
00:10:35.710 validation can refuse
00:10:39.060 to respond to us with a response and not
00:10:42.970 only does a server know that but a
00:10:44.980 client can know that too through
00:10:46.930 introspection
00:10:48.180 at the root of a graphical schema
00:10:52.020 we can find a schema special schema
00:10:55.060 field that enables us to query meta
00:10:58.600 fields on a query on a graph girl scheme
00:11:00.760 I'm sorry we can fetch the fields the
00:11:04.210 description of the fields the name of
00:11:06.160 objects and Allah is a client to be
00:11:09.070 pretty much as intelligent as the server
00:11:11.500 schema and it allows us to do really fun
00:11:15.040 stuff like Auto documentation for
00:11:17.080 example we have everything this cutomize
00:11:20.620 capable of and we have the name and
00:11:23.920 description of those fields we can do
00:11:26.650 cogeneration
00:11:27.930 imagine we have some front-end code we
00:11:32.200 can guess
00:11:33.330 the graphical types behind them because
00:11:35.740 we have the schema we can do static
00:11:38.290 validation on the client it's useless to
00:11:40.510 send a query with Yolo on my shop if we
00:11:43.210 know client-side that's not possible and
00:11:45.880 we can also do some really nice ID
00:11:48.910 integration like Auto completion of
00:11:51.400 graph QL queries validation in the IDE
00:11:54.660 and this is one example of what we can
00:11:58.750 do and this is called graphical and it's
00:12:02.170 a graphical schema Explorer a built in
00:12:06.490 JavaScript and this is really awesome
00:12:08.680 right we can navigate through our entire
00:12:10.630 API really easily and we know everything
00:12:14.110 that's possible on the right hand side
00:12:15.520 here and it's really super fun to test
00:12:18.610 and that's when I found that tool it's
00:12:20.680 really when I really got amazed by graph
00:12:22.870 girl kind of looked like this
00:12:26.460 so so far we've been sending like a huge
00:12:30.310 query with everything we need into the
00:12:33.550 graph girl server but sometimes we like
00:12:36.100 as developers to decompose thing into
00:12:38.980 smaller things and maybe recompose them
00:12:40.630 later and
00:12:41.880 like we do that with modern UI
00:12:44.830 frameworks like react right we divide
00:12:47.200 stuff in components and for example if
00:12:50.290 we had a product component here in
00:12:52.540 reality the only data it cares about is
00:12:55.990 the product data right so the ID name
00:12:58.870 and price so it would be nice if we had
00:13:01.930 that kind of abstraction in graph QL -
00:13:03.730 and it turned in turns out it exists and
00:13:06.670 it's called fragments
00:13:08.220 so we can extract certain parts of our
00:13:10.960 queries into fragments
00:13:13.230 and all we need is name it and the type
00:13:16.630 on which it applies and we can reuse
00:13:18.940 that fragment inside our original query
00:13:21.160 and that allows us to do really fun
00:13:24.339 stuff especially with
00:13:26.050 and modern UI frameworks where we have
00:13:28.769 components we can do something like this
00:13:31.420 where each component has its own
00:13:33.040 fragment and
00:13:34.350 at runtime when the query is actually
00:13:36.790 sent it's like great I created it into a
00:13:39.310 big bigger query and there's not only
00:13:43.390 reads right we can write
00:13:46.110 with graph QL - and they're called
00:13:48.850 mutations
00:13:49.800 and a mutation is very close to a normal
00:13:53.019 field except they're not nested we have
00:13:56.649 a mutation route and a query route and
00:13:58.870 on the mutation route it's only
00:14:00.880 top-level actions such as create product
00:14:03.760 here and they have a side-effect but we
00:14:06.730 have the same capabilities of like
00:14:08.500 getting only what we want back from the
00:14:11.680 result
00:14:12.660 and the cool thing about gradual is that
00:14:16.360 you don't really need to change much
00:14:17.950 about your existing business logic it's
00:14:20.560 all backed by your code and
00:14:23.160 in Ruby
00:14:25.440 we can use graphical Ruby which is an
00:14:28.450 awesome gem and it basically allows us
00:14:30.790 to create that schema and
00:14:33.930 execute the queries we receive so let's
00:14:37.240 go through a bit of a code examples - so
00:14:40.270 you take a look at how it looks like so
00:14:43.209 let's start with maybe defining our
00:14:45.190 product type and that's quite simple we
00:14:48.070 give it a name and a description it's
00:14:49.779 the basic stuff and then maybe we'll
00:14:52.029 have fields on that product so for
00:14:54.910 example the field name here is pretty
00:14:57.220 much just a one-to-one mapping with the
00:14:59.200 database we're just getting object name
00:15:01.920 by the way every field has a resolved
00:15:05.380 function here which takes three
00:15:07.959 arguments object as a first argument is
00:15:11.110 the parent object so it would be the
00:15:13.180 product here args which are arguments
00:15:15.910 you've passed to the field and context
00:15:18.100 which is a kind of top-level context you
00:15:21.430 pass with your query that could contain
00:15:23.500 any like session related stuff
00:15:25.740 authorization authentication and
00:15:28.899 anything else really but other fields
00:15:32.110 are not one-to-one mappings to the
00:15:34.329 database right we can compute some new
00:15:37.000 fields like price might be
00:15:39.000 a calculation like this
00:15:41.480 so now that we have our product type we
00:15:44.160 can maybe have our shop type where we
00:15:46.140 define our products field on it and it's
00:15:49.200 quite simple to be a large schema right
00:15:50.790 we have a query type here which will
00:15:52.500 read a route and we build our schema
00:15:55.280 just like this
00:15:58.040 so the tricky thing here is that our
00:16:01.050 queries can be pretty large right so we
00:16:04.560 can't really use gap because query
00:16:06.450 parameter din length right so we'll have
00:16:08.880 to post to our endpoint and let's take a
00:16:11.640 look at our controller we'll need three
00:16:13.980 things right the query string which will
00:16:16.110 contain our query variables that are any
00:16:19.890 variables we're gonna pass to our fields
00:16:21.420 and the context object I was talking
00:16:24.510 about and
00:16:25.700 with these three things what we're gonna
00:16:29.130 do is simply tell our schema to give us
00:16:32.280 a response it's very simple and funnily
00:16:35.340 enough using graph QL
00:16:37.670 helps you basically our controller here
00:16:40.200 only takes care of HTTP stuff right you
00:16:42.510 might use a
00:16:43.700 cookies session and then the rest is all
00:16:47.480 given to your schema so that's pretty
00:16:50.400 fun
00:16:51.470 but it's not a silver bullet right it
00:16:54.089 definitely has maybe some issues and
00:16:58.080 more complex stuff that we need to work
00:16:59.910 around and the first one is the infamous
00:17:03.540 and +1 queries and
00:17:06.079 let me give you this example to
00:17:08.730 understand better let's say we have on
00:17:09.990 our shop type the products field which
00:17:12.660 returns an array of products on your
00:17:14.699 shop and let's say we have image field
00:17:18.510 on that product type and the image type
00:17:21.420 is the image field is very simple it
00:17:23.520 just gets the image of the product if we
00:17:25.980 send a query asking for all the products
00:17:28.319 on a shop with these types something
00:17:30.930 like this would happen right each image
00:17:33.870 is loaded individually and that's
00:17:35.790 because the resolve function horror
00:17:37.680 fields are not ran in batch right
00:17:40.590 they're ran in different contexts and
00:17:42.600 they can even be ran concurrently
00:17:45.830 so a Shopify we actually built a
00:17:49.590 solution for this called graph called
00:17:51.330 batch
00:17:52.120 and it's quite simple you define loaders
00:17:56.039 which will take care of loading that
00:17:59.350 image for example and here what we're
00:18:01.720 saying is that instead of fetching the
00:18:05.230 image of the product right now just take
00:18:08.710 the ID remember it and when all the
00:18:12.400 resolves are bran batch it and load all
00:18:15.789 these images at one time and that helps
00:18:18.880 us avoid that N+ 1 query really easily
00:18:23.190 another problem is HTTP caching right
00:18:25.750 you've seen our curries can be pretty
00:18:27.340 big and we end up having to use post to
00:18:30.700 get them and the solution to this
00:18:33.789 problem is actually quite complex and
00:18:36.520 might I've afraid of a few people when
00:18:40.450 you see this but it's a client-side
00:18:41.799 cache
00:18:43.200 that's the solution most people tend to
00:18:45.580 go towards because of the HTTP caching
00:18:48.010 that we lose and that's usually a
00:18:50.890 normalized cache that we use because
00:18:53.649 take a look at these queries let's say I
00:18:56.110 fetch all the products on a shop but I
00:18:58.929 have another query after where I fetch
00:19:01.029 one particular product with ID 1 if I
00:19:04.630 was to cache them on a client side in
00:19:06.460 the waiter structured right now maybe in
00:19:09.880 the first query here I have the product
00:19:12.370 with ID 1 and in the second one I also
00:19:15.130 have the product with ID 1 but there'd
00:19:17.200 be located in two different places in my
00:19:18.760 cache right because one would be under
00:19:20.230 the products key and the other one might
00:19:22.000 be under the product 1 key right so what
00:19:25.870 ends up happening in our client-side
00:19:27.520 caches is we're gonna use link we're
00:19:30.309 just gonna normalize our data
00:19:32.909 something like this right products
00:19:35.350 instead of having the actual product
00:19:37.090 here we're gonna have a link towards the
00:19:39.600 actual product and now both queries are
00:19:42.490 in sync because they point to the same
00:19:44.260 product and
00:19:45.779 a polo and relay are two examples of
00:19:49.779 client-side caches and they're really
00:19:51.520 awesome and the reason why they're so
00:19:53.799 awesome is that having a client-side
00:19:55.870 cache not only resolves that problem
00:19:58.000 where we lost HTTP caching but we can do
00:20:01.419 fun stuff on the client now because we
00:20:03.520 have all that data right so what Pollan
00:20:06.820 really can do for example is dipping
00:20:09.550 your query before sending it to the
00:20:11.800 server for example if I have a query
00:20:14.560 that asks for the name of my shop and I
00:20:18.190 have another query that asks for name
00:20:19.960 and description my client-side cache is
00:20:23.020 intelligent enough to say I already have
00:20:25.930 name in my cache so I'm gonna diff the
00:20:29.110 ast of that graph QL query and simply
00:20:32.320 keep product description because we
00:20:35.200 don't need name right
00:20:36.660 and another thing to keep in mind is
00:20:38.920 security and if you read on hacker news
00:20:41.710 about red graft well there's always this
00:20:44.350 one person that says graph girls not
00:20:47.260 secure never gonna use it you can query
00:20:49.930 anything in your database it's not
00:20:51.940 secure but by now you all know that
00:20:54.460 we've defined our schema ourselves and
00:20:57.340 defined only the fields that we want to
00:20:59.770 expose so that's not really a security
00:21:02.080 issue but what people can do though is
00:21:04.630 create malicious queries and malicious
00:21:08.020 queries I mean very complex queries that
00:21:10.480 might overload your server because
00:21:12.550 nothing stopping you from having
00:21:13.960 circular data in your schema right
00:21:16.950 product might point to an image and
00:21:20.080 image point might point to a product for
00:21:21.940 example and somebody could craft an
00:21:24.310 insane query that would overall your
00:21:26.530 server and there's a few things we can
00:21:28.300 do to stop that we can use simple
00:21:30.790 timeouts just dropping a query if it
00:21:34.030 takes more than one second for example
00:21:35.850 but we can do more clever stuff like
00:21:38.860 having a max query death so the server
00:21:42.430 while executing a graphical query might
00:21:45.460 keep in mind at which death he is and
00:21:49.110 let's say if you said max def 10 at 10
00:21:53.260 we drop that query and we can also do
00:21:55.930 other things like query complexity which
00:21:58.240 basically you give a score to each field
00:22:01.420 and
00:22:03.120 while executing by adding these course
00:22:05.980 if it's bigger than that max score we
00:22:08.860 drop that query to
00:22:10.830 so everything I've shown so far is part
00:22:13.960 of the graph fuel spec and we can use
00:22:16.870 right now in most graphical servers but
00:22:19.360 there's also some coming in development
00:22:21.840 that are really interesting too and one
00:22:24.480 of them is subscriptions so we've seen
00:22:27.210 that we have the ability of querying
00:22:29.160 exactly what we want and we have that
00:22:32.250 client-side cash to keep it but it's
00:22:34.710 pretty hard to invalidate right and what
00:22:37.200 if you care a lot about the inventory of
00:22:40.080 a certain product for example it would
00:22:42.990 be nice to have real-time updates and
00:22:45.090 that's exactly what subscriptions do
00:22:47.780 they look like normal feels do but
00:22:51.450 instead you indicate to the graph QL
00:22:53.429 server I really care about products and
00:22:56.070 the inventory so every time that changes
00:22:59.510 send me the response again and that's a
00:23:03.420 pretty cool feature that I'm excited to
00:23:05.100 see landed soon I think another really
00:23:08.460 cool feature that's coming is Deford
00:23:09.870 queries
00:23:11.270 so imagine you have that query we fetch
00:23:14.520 the name description and products of a
00:23:17.370 shop
00:23:18.110 but in reality maybe we want to show on
00:23:22.320 a client side we want to show the name
00:23:23.850 and description as fast as possible
00:23:25.559 especially on slow clients and maybe the
00:23:29.040 products of that shop we we can afford
00:23:31.230 to have a little later and we can do
00:23:34.350 that with what we call in graph gala at
00:23:36.330 the directive at defer here which
00:23:39.780 basically indicates to the server listen
00:23:42.390 I really want name and description now
00:23:44.130 if products takes a long time to compute
00:23:46.800 for example just send it to me later and
00:23:49.830 what is it happening is that we're gonna
00:23:52.470 split that ast into we're gonna get the
00:23:56.070 first one and then the second one later
00:23:59.630 so let's go back to our original
00:24:02.900 client-server relationship we had the
00:24:06.090 typical conversation we have give me
00:24:08.520 this resource to the ID and the server
00:24:10.710 would answer with a resource but even
00:24:14.400 worse maybe the server answered with a
00:24:16.320 bunch of HDFS and the client wants all
00:24:19.500 of those two and the server is kind of
00:24:21.120 sad right
00:24:22.790 but we're back trail we kind of inverse
00:24:26.040 that relationship we changed it a lot
00:24:28.800 because clients are requesting data
00:24:31.740 shapes instead of resources this time
00:24:34.050 and the server knows what's possible
00:24:36.620 so it tells the client here is
00:24:39.600 everything you can do so we expresses
00:24:42.210 the capabilities and the client just
00:24:44.820 knows what
00:24:46.850 it needs right and it needs at data
00:24:50.040 shape not a particular resource that's
00:24:52.080 really cool and that's real separation
00:24:54.690 of concerns right because when a client
00:24:57.410 requires more fields or needs different
00:25:00.330 fields the server really doesn't care
00:25:02.430 and that brings us to really awesome
00:25:05.850 things that graph you all does well its
00:25:08.490 efficiency right because we've cut down
00:25:10.530 the round trips we do one query and
00:25:13.670 predictability because we only query
00:25:16.440 what we need we don't over fetch we
00:25:19.170 don't under fit and notice we've never
00:25:22.080 seen any like select star in these
00:25:24.360 queries we have to go down to leaf nodes
00:25:27.300 and saying exactly what we need
00:25:30.530 so I'm really excited to wear graph girl
00:25:34.290 is going
00:25:35.300 just last week github announced that
00:25:38.640 they were releasing a public graph QL
00:25:40.670 API we've been playing with it at
00:25:43.770 Shopify - and we have a lot of fun I
00:25:46.020 bunch of companies and updating it so
00:25:49.380 I'm really excited to see where it's
00:25:50.700 going and I hope
00:25:52.040 you guys give it a try at least and have
00:25:55.920 some fun with it - thank you
00:26:05.990 thank you Mark I hope next year when we
00:26:09.269 ask how many people use graph curl there
00:26:11.279 will be like a wall of hands it looks so
00:26:13.799 awesome if you have any questions from
00:26:15.720 OC's grab him in the hallway and chat
00:26:19.139 with him and we're gonna have a ten
00:26:20.880 minute break sure you check the coffee
00:26:23.309 and the sweets in the sponsor skull and
00:26:25.649 we'll be back in ten minutes thank you
00:26:35.510 you