27 comments

[ 2.2 ms ] story [ 26.3 ms ] thread
Falcor is still in developer preview (https://github.com/Netflix/falcor). Otherwise the API (both on the server and the client side) look simpler than anything else I've tried so far.
At a glance seems the goal is similar to GraphQL?
At least it feels like they're trying to solve the same problem.
they are. Falcor is more lightweight and a bit easier to grok imo
It might be a clean API but it was developed to solve a problem that nobody besides huge companies like Netflix have to the detriment of REST API design and a clean network protocol.

You are also bound to use both their client-side AND server-side libraries which locks you completely in.

REST is inadequate even for smaller companies, when it comes to the use cases Relay+GraphQL (or Falcor) tries to solve.

1. Under fetching and over fetching.

2. REST is great for CRUD, but not everything is that simplistic. Eg: Changes spanning multiple entities with transaction support.

3. Patchy PATCH support. Also, endless debates on whether something should be a PATCH or a PUT or a POST. The answer in some of those cases was that it couldn't be solved with clean REST.

(Edit: added GraphQL)

Do you have use cases that won't fit in a REST design ?

I'm genuinely curious because as a web developer most of the problems I have encountered can be solved with API versioning, filters, paginations, scopes (limiting returned fields) and hierarchical URL structures (e.g: /users/:userId/comments/:commentId).

Let me use the example you have.

1. Clean RESTful URLs like the one you have doesn't make it easy to fetch { article, article.author.name, [user.comments.commenter] } in a _single call_. GraphQL let's you define the Shape you want.

2. Updates spanning multiple resources aren't a good fit for a Resource Oriented pattern like REST. a) How do you delete multiple comments (Ids 1, 34, 44) in one shot? http://stackoverflow.com/questions/7511195/rest-architecture...

3. How do I edit /users/200 and /users/201 in one single call? Imagine a Grid with a Save Button. Also, this could be a transaction as well.

The above is doable with REST, but it is kind of a grey area and loses some of the obviousness seen in clean URLs such as in your example.

I agree that those cases would be tough to make work in a "clean" or at least standard RESTful API design but it's really improbable to encounter them.

1. This issue could be attributed to the database schema design imo.

2. In what case would you want to delete multiple comments at the same time ? I'm not trying to argue for the sake of arguing but I've genuinely never had to remove parts of an array that were not either a single element or the whole array.

3. Again I don't see a scenario where you would have to do this. If it's a consequence of another API call for example: You DELETEd a "group" so all of its member "users" should be deleted too. Than this kind of side effects or consistency CRUD should be handled inside the DELETE API call of the "group".

I don't think that REST API design pretends to answer every single business logic use case but it does answer most of the common ones.

In my opinion it's also dangerous to use a library that will abstract those difficult / unconventional use cases because they will feel easy to solve and hide the inherent complexity and cost that is present in the Database queries.

Case for point 2: Comment administration page. You get a list of comments with checkboxes, check the ones you want to select and then click "Delete selected".

Case for point 3: Like he said, a grid (with inline editing) and a "save" button.

3. If you have a grid you also have pagination which eliminates the possibility of editing multiple rows in the same call.
I've put some thoughts below with references to cookbook recipes, I'm not saying they are in sweet point for a lovely resource oriented design but they are things you can handle.

1. Recipe 2.4 is one option. Alternative might be granular resources, if the characteristics of your use case means they can be done efficiently. For example we might include the URL to author details inside the article. That means another request, but if those author details are made immutable (as in change to author details means new URL), then they can be given a long cache period. Also HTTP/2 will mean more granular resources have different performance characteristics.

2. Recipe 11.10 could work so the URL would be the comments collection as a whole, I'd use PATCH (or POST if PATCH isn't an option) to then send the updates you need. So a PATCH to /<posturl>/comments with the result body including information that causes those comments to be deleted.

3. Same idea as 2, I'd use PATCH to the collection or a custom resource.

Is it unfair to think you're saying that a leaky abstraction is good?
I think it depends on the case but my point is that if you hide to the developer the cost of that abstraction than you will get some surprises in performance later on.

There are lots of reasons why an abstraction was written, ease of use being one of them but this also means that they don't always cover all bases (like performance). Which is alright if you (the developer) know about it.

Thanks to GraphQL or Falcor I can most likely do something like "return me an object containing table1.colA, table2.colB, table3.colC, ...etc." very easily but it also means that I just asked for at least two joins.

This can get really expensive if every developer on that project has the ability to do costly queries like this.

Falcor is intended to be used as a router to microservices, which could even be a REST api, not to database directly. A microservice would be between Falcor and the database. It isn't an ORM. It won't build a query. The services Falcor gets data from should have sensible limits that prevent unacceptable performance, whether you use them with Falcor or not.
The page linked to in the second point mentions "Restful Web Services Cookbook", it's a while since I've read it but my memory is as the the author says it covers solutions for each of the three issues you are raising.
> 1. Clean RESTful URLs like the one you have doesn't make it easy to fetch { article, article.author.name, [user.comments.commenter] } in a _single call_. GraphQL let's you define the Shape you want.

/api/article/12/full to return the article with author and comments, and /api/article/12 for just the article text would work and aren't all that dirty. Could also be arguments to the REST call, but that makes it a little more ambiguous since you could have several different code paths for the same endpoint.

> 2. Updates spanning multiple resources aren't a good fit for a Resource Oriented pattern like REST. a) How do you delete multiple comments (Ids 1, 34, 44) in one shot? http://stackoverflow.com/questions/7511195/rest-architecture....

The article you linked has a pretty graceful answer, I'm not sure why you dislike it. REST is generally a hierarchical datasource. Implement an endpoint above users in a hierarchy, or give it it's own tree. I.e. /api/comment/multi/delete, or /api/comments/delete (vs /api/comment). It's really not all that bad to do, and in a lot of cases you could use the same code to actually do the action.

> 3. How do I edit /users/200 and /users/201 in one single call? Imagine a Grid with a Save Button. Also, this could be a transaction as well.

This is pretty much the same problem, you just have to handle more data. Again, /users/multi/update and POST your data.

The biggest place REST falls short of other HTTP-based API architectures is when you have a lot of different fields that need to be relatively randomly accessed. Sometimes you want the article with the authors name and date but no comments. Sometimes you just want the article name and author's name. Sometimes you just want the text. etc, etc. REST fails when you try to use it as SQL over HTTP, which looks to be what GraphQL is trying to do. And it's worth noting that it doesn't really "fail" per say, you just end up with a bloated mess of endpoints if you need to have 20 different variations on the data you need for an endpoint.

1. I think though you'd really want to have some measurements regarding the performance impact of things like over fetching.

Also remember that having a resource oriented design and working well with HTTP gives you out of the box advantages in terms of caching and validation, and in HTTP/2 you get extra efficiency advantages (e.g. lots of more granular resources can be retrieved over a single connection).

2. There are patterns for that though, often best approach is to represent that transaction as a resource. Restful Web Services Cookbook covers approaches for these sorts of bulk operations.

3. Not sure that's an argument against going resource oriented, if you don't find the debate interesting just ignore it.

> REST is inadequate even for smaller companies, when it comes to the use cases Relay+GraphQL (or Falcor) tries to solve.

Maybe it's slightly harder to implement those things in REST, but REST gives you HTTP caching and that's a killer feature. If you'd prefer to re-invent caching so you can use POST everywhere be my guest.

> Also, endless debates on whether something should be a PATCH or a PUT or a POST.

An often overlooked technique for handling such arguments is to quit bickering and get back to work solving the business problems.

Anyone who builds APIs that talk to microservices has this problem, not just huge companies.

As for the lock in, working in this paradigm would be impossible without a smart client library. Similarly, GraphQL has Relay. But Falcor's client side library is much more flexible than Relay, which is only a wrapper around React apps. If you have a non-React project, you have to use Falcor.

Small note on Falcor and its paradigm - in huge, complex applications, delaying errors until runtime is something to be avoided. Using Falcor seems like it'll be prone to that.

On the other hand, ASP.NET MVC or Web API will give you intellisense when consuming your endpoint.

From an earlier @falcorjs tweet: @evanwinslow Not out of the box. However the great thing about a untyped schema, is that you can always layer a typed schema over it. https://twitter.com/falcorjs/status/596416048988966912?s=08

The reason Asp.net MVC and Web API gives you type information is because a) you've already given type information b) tooling

You can overlay schema on Falcor API and verify it as part of the build. The tooling for the probably doesn't exist right now, but the building blocks for tooling do. Actually, your point is more about JS vs a statically typed language.

Yep, and Relay/GraphQL do this so that would be a place to look at how it'd be done.
can anyone tell me why Falcor and/or GraphQL is better than using hypermedia apis and a orchestration layer service?
I don't have a problem with the concept behind Falcor and GraphQL. My problem is the execution and the fact that one has deal with yet another layer of complexity on top of everything else, which expose an ORM,RPC like framework on both side, and make things more difficult to cache. There has to be a better compromise to achieve the same goal.

EDIT: Or let's go full AMF again and use classes and objects defined on the server in the client... I fail to understand how Falcor and GraphQL are a better alternative to what already exists. Why limit it to queries then ? let me get my FactoryFactories right back in the client instead of yet another format, since REST is basically thrown out of the window anyway.