Glossary

__typename

A meta field that is implicitly present for every field. Its value is the name of the type. Most useful for union types and interfaces.

# schema
type Query {
  user: User
}

# query
query MyQuery {
  user {
    username
    __typename
  }
}

And the response:

{
  "data": {
    "getCurrentUser": {
      "username": "admin1",
      "__typename": "User"
    }
  }
}

See more in the __typename chapter.

Alias

When a client query wants to include the same field multiple types, for example with different arguments, it can differentiate by using different names for the fields. This is called an alias.

For example, this query includes the tickets with two different statuses:

# schema
type User {
  username: String!
  tickets(status: STATUS): [Ticket!]!
}

# query
query {
  user(id: "user1") {
    open_tickets: tickets(status: OPEN) {
      id
    }
    in_progress_tickets: tickets(
      status: IN_PROGRESS,
    ) {
      id
    }
  }
}

See more in the Aliases chapter.

Arguments

An argument is a parameter for a field. The schema can define optional (no !) and required (! at the end) arguments. Arguments are typed values, and they can be scalars or input types.

This schema defines a field with a required, one with an opitional argument, and one that does not support any:

type Query {
  # No ! after String, so this is an optional argument
  allUsers(search: String): [User]

  # The username is a required argument
  user(username: String!): User

  # no arguments
  issues: [Issue]
}

The client query can then define arguments for fields that support them:

query Query1 {
  # search for admins
  admins: allUsers(search: "admin") {
    username
  }

  # search for all users
  users: allUsers {
    username
  }

  # get a specific user
  user(username: "user1@example.com") {
    email
  }

  # get all issues
  issues {
    due_date
  }
}

See more in the Arguments chapter.

Cursor-based pagination

A pagination style that allows retrieving the next page of item using a cursor value returned by the last query. This is how DynamoDB and some of the other NoSQL databases work.

When you send a query, the database returns a pagination token when there might be more items to fetch. In the case of DynamoDB, the result might contain a LastEvaluatedKey which the next query can pass as the ExclusiveStartKey. This fetches the next page.

The DynamoDB AppSync data source returns a nextToken instead which is a stringified and encrypted version of the token. But, as a convention, these tokens should be only used for fetching the next page.

Advantages of this pagination style are constant performance for all queries and that pages won't shift when items are added or removed.

A disadvantage is that it does not support locating an item in the whole result set. This makes it hard to accurately show things like items 31-40 as later queries don't know if items are added or removed.

The alternative pagination style is called Offset-based pagination.

See more in the DynamoDB pagination chapter.

Data source

Data sources interact with some external service, such as a database or a Lambda function. They provide an interface for AppSync to use resources in the AWS account and outside of it.

Each resolver is configured with a data source and the role of the request and the response mapping templates is to provide the input arguments and process the response of the data source.

See more in the Data sources chapter.

Directive

Extra metadata in the schema for types and fields, for example to define authorization rules.

For example, the @aws_cognito_user_pools directive restricts the allUsers query to be only available for administrators:

type Query {
  # only admins can query all users
  allUsers: [User]
  @aws_cognito_user_pools(cognito_groups: ["admin"])
}

See more in the Directives chapter.

Field

A field is a property in a type. Fields can be scalars or complex types. This type defines three fields, two calars and one complex type, defined elsewhere in the schema:

type User {
  username: String!
  email: String
  issues: [Issue!]!
}

Inline fragment

A way for a client query to differentiate result objects when a field can be return multiple types, which is the case for interfaces and union types.

An inline fragment for an interface:

# schema
interface User {
  # ...
}

type AdminUser implements User {
  # ...
}

type NormalUser implements User {
  # ...
}

type Query {
  allUsers: [User!]!
}
# query
query MyQuery {
  allUsers {
    username
    email
    ... on AdminUser {
      permissions
    }
    ... on NormalUser {
      nickname
    }
  }
}

An inline fragment for a union type:

# schema
type Query {
  search(query: String!): User | Issue
}
# query
query MyQuery {
  search(query: "test") {
    ... on User {
      username
     	email
    }
    ... on Issue {
      text
    }
  }
}

See more in the Inline fragments chapter.

Input type

A type that can be used in arguments in the schema.

input UserInput {
  username: String!
  avatar: String
  cv: String
}

type User {
  username: String!
  avatar: String
  cv: String
}

type Mutation {
  addUser(user: UserInput): User
}

Covered in the Input types chapter.

Interface

An abstract type that allows other types to implement it. Fields can define this abstract type and queries can define what fields to retrieve using inline fragments. Interfaces are a better alternative to Union types when there is a logical common ancestor for the returned types.

interface User {
  username: String!
  email: String
}

type AdminUser implements User {
  username: String!
  email: String
  permissions: [String!]!
}

type NormalUser implements User {
  username: String!
  email: String
}

type Query {
  # this field returns a list of User objects
  allUsers: [User!]!
}

See more in the Interfaces chapter.

Mutation

Mutations are the operations that change data. They can get input arguments that parameterize how they work, and they can return scalars and complex types as well. The implementation is defined by a resolver.

For example, this mutation creates a new user and returns the object:

type Mutation {
  createUser(username: String!, email: String): User
}

See more in the Mutations chapter.

Offset-based pagination

A pagination style where the items to fetch is defined by an offset that drops a number of items from the result. This is used by most SQL databases along with the LIMIT clause.

This provides a consistent view as each query knows which elements are in the result set making it easy to show a breadcrumb such as items 31-40.

The disadvantages are non-uniform performance (when the offset is large queries are slower) and fetching the next page might show duplicated results or skip some if items are added or removed between the calls.

The alternative pagination style is called Cursor-based pagination.

Orchestration endpoint

An API endpoint that aggregates requests to other parts of the API. For example, there might be endpoints to fetch orders and products, but when a client needs details for the products in an order it needs to sent multiple requests. An orchestration endpoint that fetches the order and all the products in it saves the client from making additional roundtrips.

See more in the Orchestration endpoint chapter.

Overfetching

A problem with a query where the client gets more data than it needs. It is wasteful on the backend as it needs to fetch the additional data, and also wasteful on the network as it transfers bytes that are then discarded on the other side.

This usually happens when an endpoint returns a complex object and the client has no way of defining which fields it will use.

See more in the No overfetching or underfetching chapter.

Query

An operation that retrieves data through a GraphQL API. This is a field of the Query type and it can receive arguments and return scalars and complex types as well.

type Query {
  user(username: String!): User
}

See more in the Queries and Mutations chapter.

Resolver

A resolver provides a value for a field, in practice that is the implementation behind the GraphQL schema. See more in the Resolvers chapter.

Scalar

A simple type that can be directly translated to a primitive value. Some scalars are guaranteed by the specification to be present, and the GraphQL server can also define additional ones. The predefined ones are:

  • String
  • Int
  • Float
  • Boolean
  • ID

For example, this type defines two scalar fields:

type User {
  username: String!
  email: String
}

See more in the Schema chapter.

Schema

The main GraphQL document that defines what types, queries, and mutations are possible in the API.

A schema that defines a type, a query, and a mutation:

type User {
  username: String!
  email: String
}

type Query {
  user(username: String!): User
}

type Mutation {
  createUser(username: String!, email: String): User
}

See more in the Schema chapter.

Subscription

TODO

Trivial resolver

A resolver that simply extracts the matching field from the source object. Useful when the parent resolver returns an object that matches the GraphQL type which is usually the case when the object comes from a database.

See more in the Nested fields chapter.

Type

A type is a complex object defined in the GraphQL schema.

For example, this is a User type with two fields:

type User {
  username: String!
  email: String
}

See more in the Schema chapter.

Underfetching

A problem with a query where the client gets less data than it needs, so it needs to send follow-up requests. Since the number of roundtrips are the main contributor to the slowness of an application users experience, underfetching has a direct impact on UX.

This usually happens when a query can return a single object type and to provide all the data the client needs to send requests to other endpoints as well.

See more in the No overfetching or underfetching chapter.

Union type

A field that can be one of several types. Client can use inline fragments to define how to handle each types.

type User {
  username: String!
  email: String
}

type Issue {
  text: String!
}

type Query {
  search(query: String!): User | Issue
}

See more in the Union types chapter.

Master AppSync and GraphQL
Support this book and get all future updates and extra chapters in ebook format.