What are pros and cons between FQL and GraphQL?

We know that FaunaDB supports both FQL and GraphQL as query languages.

What are the pros and cons of each?

When do I (or why would I) choose one over the other?

The initial choice between GraphQL and FQL is based on what you already know and what you want to learn. The initial language for FaunaDB is the Fauna Query Language (FQL). This means that language can be used for all the FaunaDB functionality.

  • Creating indexes, databases, collections, keys, roles, etc via code
  • Writing advanced role permissions
  • Writing User Defined Functions
  • Logging in (generating tokens)

In GraphQL can do a lot of things already, a lot of people are able to do most they need (or everything) with their autogenerated GraphQL API and some add some functionality (such as authentication) via custom resolvers that are implemented in User Defined Functions (written in FQL). GraphQL is great and will get you far, but at a certain point you will probably want to learn some basic FQL as well. In essence, it’s not an OR but can be an AND story.

In the long run, our GraphQL layer will offer many features but will probably (I might be wrong) never be as powerful as FQL is because the goals of the language are entirely different (we’ll get to that).

Most people choose GraphQL because it’s a familiar language, they already know it, they like the easy syntax and it’s easy to get started. That said, GraphQL is more a query language while FQL is a more like a programming language. In GraphQL, you declare what you want to retrieve and FaunaDB decides for you how it will retrieve these things (creates indexes, generates the query). In FQL you declare exactly how you want to retrieve it. The difference between what and how is the difference between a declarative language (define what you need) and a procedural (define how) language. SQL, GraphQL, etc are rather declarative, FQL is different… it’s procedural. There are reasons why FQL is procedural and those reasons are interesting to know before we go further.

  • FQL is predictable, the price of a query can be easily determined while writing the query (without having to run a query planner)
  • FQL can do everything, from User Defined Functions (stored procedures etc often requires a separate language in other query languages), to Security Roles, to complex conditional updates, to updating/reading a bunch of related documents in one query.
  • FQL consists of just functions, functions compose well. Generating or writing high-order FQL is quite easy and you can write very very fine-grained complex functionality like that.

The tradeoffs with GraphQL:

  • FQL is due to the procedural approach also a bit more verbose, GraphQL is considered very easy to use.
  • You can’t write security roles in GraphQL, you will want to use FQL there.
  • Some GraphQL functionality (range queries, filtering on multiple conditions, advanced indexing strategies) is not available yet. That might change in the future. In the meantime you can use the User Defined function ‘escape hatch’ and write a resolver which will trigger a User Defined Function. However, those are written in FQL.
  • GraphQL has a schema, and we validate input at write time, at this point FQL is schemaless. Nothing stops you though from writing an FQL query on a GraphQL generated collection which will bypass that schema.
  • In FQL you decide the execution of your query. For example, if you want to use index values instead of Map/Get (which are less flexible but cheaper) then you can do so in FQL, but in GraphQL you don’t have that control (except via UDF resolvers) since we translate the GraphQL to one FQL query and that query is based on Map/Get since we can’t create such highly specialized indexes based on the schema.
  • Complex update statements, Imagine you want to update a specific document, but only if a certain condition on another document is true, that’s easy in FQL, that’s not possible in GraphQL at this point and if I’m correct such conditional updates are not possible in any GraphQL implementation I’ve seen so far (I might be wrong)

I would also like to emphasize that it isn’t a matter of either/or, and most people are using both to some extent. FQL is unique in being a functional database query language, with all of the benefits Brecht described above, so you will inevitably find, as your app evolves, that you want to take advantage of that. And it’s not that hard to use once it “clicks” :slight_smile: