Part 1

The world’s best serverless database, now with native GraphQL

GraphQL has revolutionized the way we think about APIs. Instead of working with extremely rigid REST endpoints, GraphQL allows developers to specify the shape of the data they need, without requiring changes to the backend components that provide that data. This enables teams to collaborate more smoothly -- so backend teams can focus on security and business logic, and front-end teams can focus on presentation and usability. In this way, GraphQL has emerged as a critical layer for universal database access.

FaunaDB’s GraphQL API was first released in preview mode back in April on FaunaDB cloud. The GraphQL API has had a few incremental releases since then, with each one increasing user adoption from both partners and developers.

Ease of GraphQL, backed by the power of Calvin

FaunaDB's GraphQL API leverages the Calvin-inspired shared core to offer developers uniform access to transactional consistency, user authorization, data access, quality of service (QoS), and temporal storage.

Temporality: FaunaDB is the only database that provides built-in temporality support with no limits on data history. With per-query snapshots, any API (e.g., SQL) in FaunaDB can return data at any given time.

Consistency: FaunaDB offers the highest consistency levels for its transactions. These strong consistency guarantees are automatically applied to all APIs.

Authorization: Unlike most databases that control access at a table level, FaunaDB provides access control at the row (document) level. This fine-grained access control is applicable to all APIs, be it GraphQL or SQL.

Shared Data Access: In keeping with Fauna's dedication to modern polyglot development, data written by one API (e.g., GraphQL) can be read and modified by another API (e.g., FQL). In contrast, most other databases limit APIs to their specific datasets.

QoS: FaunaDB’s built-in prioritization policies for concurrent workloads are enforced at the database level or with access keys. All API access automatically adheres to these QoS definitions.

Highlights of FaunaDB's GraphQL API

FaunaDB's GraphQL API supports three general functions: Queries, Mutations, and Subscriptions. At this time, FaunaDB natively supports Queries and Mutations. Native support for subscriptions is in the roadmap; meanwhile, you can write a custom function to set up a subscription if necessary. (If you need help with this, reach out to us in Community Slack.)

In the following section, we will cover highlights of this release. 

GraphQL Support in FaunaDB Cloud Console

The FaunaDB Cloud Console is launching with a set of brand new features to make it easier for developers to interact with their data.

Importing the GraphQL schema definition file

To get started, simply import your GraphQL schema from the GraphQL tab in the Fauna web editor. If there’s a formatting issue with the uploaded schema, our import tool will expose the error and inform you of the specific issue:

Integrating the GraphQL Playground IDE

Long-time GraphQL fans will quickly notice that we’ve integrated Prisma’s GraphQL Playground IDE directly into the Fauna Cloud Console. This allows us to provide a lot of out-of-the-box functionality in a GUI that most GraphQL developers are already comfortable using. Among other useful features, GraphQL Playground allows you to navigate your own auto-generated API documentation with ease using the Docs and Schema tabs, as seen below:

More features offered by GraphQL Playground can be found on Prisma’s blog post.

Automatic Index Creation

When you import a GraphQL schema, FaunaDB uses the type definitions to generate the classes, and the query definitions to automatically generate the indexes.

Schema Definition

Objects generated

type Todo {
   title: String!
   completed: Boolean
}
Class Created
{"name": "Todo",
  "history_days": 30,
  "ttl_days": null}
type Query {
   allTodos: [Todo!]
   todosByCompletedFlag(completed: Boolean!): [Todo!]
}
Indexes Created:
  1. Name: allTodos. A class index with no 
terms or values
  2. Name: todosByCompletedFlag. An index 
with the term completed flag but no values. 

FaunaDB is a schemaless database, so where does Fauna store all the metadata associated with the type and query definition? Fauna stores the schema definition as part of the object metadata using a "gql" tag. This information is visible in the object definition FQL tab (in the Cloud Console).

The @relation directive

GraphQL directives help with a variety of implementation related tasks. While the most common use is to create a custom derived field, the @relation directive in FaunaDB is also used to create relationships between two types. For example, in the schema definition below, each todo belongs to a specific list while a list can have many todos. This mimics the traditional primary key:foreign key relationship. FaunaDB automatically creates the required indexes while queries are implicitly executed across classes.

type Todo {
    title: String!
    completed: Boolean!
    list: List
}

type List {
    title: String!
    todos: [Todo] @relation
}

type Query {
    allTodos: [Todo!]
    todosByCompletedFlag(completed: Boolean!): [Todo!]
    allLists: [List!]
}

The @unique directive

The @unique directive allows adding constraints to the GraphQL schema. With this directive, FaunaDB automatically creates a unique index on the term on which it is specified.

type User {
 username: String! @unique
}

Importing this schema will create a class called User and a unique index named unique_User_username. Trying to enter a duplicate username will result in an error. These directives are quite powerful as the developers can create database side objects with single keywords in their GraphL schema file.



Pagination support

Pagination support was recently added to the GraphQL service. Instead of fetching all records at the same time, pagination allows a developer to get 50 records at a time. High cardinality fields, such as `Query` object fields that return arrays or fields marked with the @relation directive, now return a `Page` object.

As an example, let's take this simple schema definition file:

type Todo { 
  title: String 
}

type Query {
  allTodos: [Todo!]
}

The corresponding allTodos query would be:

{
  allTodos(_size: 10, _cursor: $cursor) {
    data: {
      title
    }
    before    # backwards cursor
    after     # forward cursor
  }
}

The cursor variable can be used to move across the pages of data.

User-defined Resolvers

User-defined resolvers are another feature we've added in response to developer feedback on the April beta release. The @resolver directive allows a developer to associate a field in the query object to a specific user-defined function in the case of complex business logic, as opposed to the 1:1 object mapping that FaunaDB automatically generates with document terms.

// User-defined function. Create this function using Fauna Shell
CreateFunction({
  name: "say_hello",
  body: Query(Lambda(["name"],
    Concat(["Hello ", Var("name")])
  ))
})

// GraphQL Schema
type Query {
  sayHello(name: String!): String! @resolver(name: "say_hello")
}

// Calling from the GraphQL API
{
  sayHello(name: "Kate")
}

// Response
{
  "data": {
    "sayHello": "Hello Kate"
  }

Getting started with FaunaDB’s GraphQL API

Our official documentation is the best place to get started with FaunaDB's GraphQL API. We recommend completing the tutorials in the following order:

  1. Getting started with GraphQL
  2. GraphQL Relations
  3. Unique Constraints in GraphQL
  4. GraphQL Pagination

We've also added a GraphQL Reference section, where you can find additional details on topics like:

Over the last few months, we have also published a three-part series [Part 1|Part 2|Part 3] outlining how to get started with GraphQL in FaunaDB. You can start testing your GraphQL queries and mutations right away using the FaunaDB Cloud Console, Fauna Shell, or whatever other GraphQL platform you prefer.

Stay tuned for more...

Cloud developer happiness is our #1 priority here at Fauna, and GraphQL support is just the beginning. Over the next few months, stay tuned for several more big "ease of use" features that will help cement FaunaDB's place as the most developer-friendly database on the market. There has never been a better time to share Fauna with your development team and friends 😄

We also welcome your feedback! Please email me at product@fauna.com and let us know of any other features that would make FaunaDB an obvious choice for your next project.