For the past while I’ve been doing everything in my power to engrain myself with as much knowledge and practical experience with GraphQL. It’s quite a different trip from implementing a RESTful API, literally everything is different. With REST you have 100% complete and total control over everything top to bottom, but with GraphQL you have a lot of control over how it’s querying your database and how you model your data, and that’s about it.

But the things that really gets me to love GraphQL, is that it does handle everything I dislike handling about RESTful API’s, and primarily it’s all about the decision fatigue.

Allow to paint a picture using an impractical example: a blog api.

Let’s assume a data model structure like so:

Posts

  • id
  • title
  • slug
  • content
  • summary
  • author
  • category
  • tags

Author

  • id
  • name
  • email

Category

  • id
  • title
  • slug

Tag

  • id
  • title
  • slug

It should be very obvious how each piece of data relates to each other while being ambiguous enough to not matter what the data store engine is. This data could be stored inside markdown files for all it matters.

Now let’s pretend were setting up a typical RESTful api.

The first questions immediately comes to mind:

  • Do I do this SUPER faithfully restful spec? or do I roll my own endpoints?
  • Do I make use of HTTP status codes? or do I send out my errors in the payload all the time?
  • Do I support JSON and XML? or just JSON?
  • Do I model my output structure the same everytime, even with errors?
  • Do I allow my own blog to consume this API? if so, should I should include CRUD endpoints too?

Ok so we’ve come to a few conclusions, we’re still doing ok. Now, we need to talk about our first endpoint, dealing with getting posts

  • Should I use pluralized endpoints to represent lists, or singular all the time?
  • Do I use /post for multiple and /post/{id} for single, or do I use /posts for multiple and /posts/{id} for singular
  • Do I even use a separate url to represent a single object. Maybe I should just use /post?id={id} and if id is available, only get that post?

This may sound like making mole hills out of ant hills, but these are all very real decisions we make when drafting our api designs. At this point, you begin to realize that when it comes to implementing RESTful API’s, it’s getting difficult to tell exactly how strict you want to be on yourself to follow RESTful specification to the letter. Which means, you’re allowing yourself to think about going rogue. But you may still be ok at this point.

But it should already be painting a picture, of why every single “RESTful API” you’ve ever encountered, looks and behaves completely different from one another. Because you have 100% control of everything end-to-end, that also means you get to make these calls. And 200+ questions need answers at every point in the design.

Ok so you got your /post endpoint that delivers a list of posts. You’ve by now also figured out how you want to deal with pagination. For sake of argument, let’s pretend: /post?offset=0&limit=10

Hmm, ok so the default listing organization isn’t going to cut it for the front page, where you desire to have the blog posts order reverse chronologically by a Date Published field. Ok so now we include a couple more arguments: /post?offset=0&limit=10&sortBy=date_published&orderBy=DESC

Oh but hmm, should we expose an actual table field? Maybe that should be abstracted to an ENUM? And what about the sort order, should that be 1 and -1 instead? perhaps some other terminology?

These are all questions that need to be answered by you as you design it. Sure there’s answers in a spec somewhere that you can follow, and that may make answering some of these questions a lot easier. But when you’re doing that, you’re already surrendering the power of 100% complete control over to someone else’s opinion of how your API should be designed. Even more so if you just install someone else’s library that instills their decisions into how your API should react to input.

And this is just for posts. And we’re not even done!

Ok so, and this one is my favorite question to answer: How to handle the relationships. There’s so many questions that need answers.

  • Do I include the author, category, and tags in the posts endpoint? The answer is probably yes for this one. Pretty easy. But
  • Do I only include the reference ID to query for that object separately in a different call?
  • Maybe then do include a nested URL to the appropriate API to call for that object?
  • Maybe I just include the relationships by default?

Oh but wait, now here’s where it starts getting bloated.

Now not only are you contemplating including WHOLE other nested objects in your posts api, you’re also opening up a new can of worms: bloating the output buffer. Posts by themselves can do this pretty easily themselves, especially if your blog includes some pretty lengthy posts. All of that needs to be serialized and pushed out to the client. And the longer it takes to transfer your json/xml payload to the client, the longer not only do people have to wait for their page data, but the longer it takes for your servers request thread to be fulfilled and closed, and database connection thread to be recycled. So maybe including the author and the category wont be such a big deal, but tags? Depending on how tag hungry an editor is, this can get pretty bloated pretty quickly too.

Ok so, lets answer this then

  • Perhaps then maybe, I include the author and category on the list view automatically, but I put in a extra argument to include the tags or not?
  • Do I assume the order of the tags once they’re included?
  • Should I include the ability to turn some fields on and off?

And pretty soon you get a endpoint that resembles something out of a horror movie: /posts?offset=0&limit=10&sortBy=publishedDate&orderBy=reverse&tags=true&content=false&summary=true

And then you get to answer: How am I going to document this?

Pretty soon your frankenstein of an API may perhaps derail further as you realize Swagger has it’s own opinions, and it just gets messy. At the end of the day, you have a working, usable API that can be queried to get your data, and it may even be well documented and ready to go.

But now we start to think about how to deal with Categories.

You get the picture.

In Part 2, I’ll discuss how GraphQL both answers all these questions FOR you, and yet, you still get full control over how everything works.