We are gradually migrating our REST integration to GraphQL. In each part of the migration we have found ourselves pulling our hair out due to the ‘design’ of the GraphQL API, or rather, the complete lack of it.
This is a continuation of the below discussion.
As some background we have a middleware/integration platform for medium size businesses. We have integrated with Shopify from the start. We offer about 30 functional (read/write) endpoints with Shopify, covering order processing, inventory/item/pricing and customer handling.
I can understand that as Shopify grows, there probably needs to be some difficult decisions, however….
Problem
The GQL API seems to be a direct view of the Shopify’s database.
The extreme fine grained catalog/publication mutations is an example. Why do we need to issue a separate GraphQL mutation to link the publication to the catalog, when there is likely a 1:1 relationship?
Other examples include the companyLocationAssignTaxExemptions, LocationCreateTaxRegistration and see below.
The general sense of the GQL API seems to have no regard to sensible defaults that I assume most of your customers would only ever need.
Problem
What took a single REST call now takes multiple GqL invocations.
For example, creating products with variants now takes at minimum 2 GQL calls - one for the product, one for the primary variant. A sensible implementation would be to fold these operations into one.
If you wish to create/update a product with variants you now three GQL invocations? Why do we need a productCreate vs. productUpdate, and a productVariantsBulkCreate vs. productVariantsBulkUpdate mutations? This requires splitting out the variants into create and update sets and submitting separate requests? The distinguishing factor is variant id → the Shopify API should just use that and perform the necessary insert/update (upsert) handling.
Similarly the companyCreate is a good API, but an update now requires 5 separate mutations!
Problem
No Atomicity
Because of the two problems above, transactions that were (we assumed) atomic in the REST API are now spliced over multiple separate invocations. An error can result in logical writes which are half written. Salesforce, for example, allows you to combine operations into a single request which will fail atomically.
Problem
No External Ids
We find ourselves having to query Shopify to translate a description (or partial description) into an id so that we can make the insert/update. A better approach (also see Salesforce) would be to allow most records/objects to be tagged with an external id. This would (in our opinion man) reduce the number of queries and permit objects to be identified with the external id.
The Upshot
What was a nice solution to integrate with, is now tedious. For each of our write integration points we now need to create a public façade where the API resembles the well-designed, nice REST API, but our new backend implementation now does all the fiddly/fine-grained GQL queries and mutations. You may not care, but our small company has gone from being a Shopify advocate to one where we now sit on the fence.