Skip to main content
Version: 0.4.x


Learn how to write high-quality GraphQL schemas for your models.


ComposeDB models are written in GraphQL using GraphQL Schema Definition Language (SDL). Your schema defines a collection of object types and the relationships between them. Those types will have scalars (values), shapes (key-value mappings), and lists to describe the structure and validation rules for the model, and use directives for other metadata information.

We currently support a subset of SDL’s scalars and directives, but are continually adding more, see the reference for a complete list.


Learn about key concepts for the GraphQL Schema Definition Language.


On this page, we provide basic info for you to begin writing GraphQL data models. For more complete information on the GraphQL Schema Definition Language, visit the GraphQL website.

Shapes, Fields, Scalars

The most basic component in a GraphQL schema is an object type, sometimes called a shape. It simply represents the shape of the data you want to query and its properties, consisting of fields (keys) and scalars (values).

type EducationModule {
module_name: String!
module_domain: String
number_of_topics_covered: Int!
learners_enrolled: [Learner!]!


  • type defines a new object
  • EducationModule the name given to the object; queryable
  • module_name, module_domain, number_of_topics_covered and learners_enrolled are fields in the EducationModule type; all fields are queryable
  • String! and Int! define the data type of the value. By adding ! to the end of the type declaration, we are telling GraphQL to always return a value when we query this field, which also means that when writing data through a mutation a value is required.
  • [Learner!]! defines the data type of the value, but in this case the data type is an array of another type, Learner, which is not depicted above. It is required since it includes the !.


Enums represent the type of a single string value in the schema from a set of accepted values, for example:

enum NoteStatus {

Special Types

GraphQL reserves the use of two special type names, query and mutation.

Do not name any of your own custom types, which are the majority of the types you will work with, the same as these two special types.

  • query type is used as the entry point when retrieving data using GraphQL
  • mutation type is used as the entry point when writing or changing data using GraphQL

Embedded Shapes

Our first shape, EducationModule, makes use of an embedded shape called Learner:

type EducationModule {
module_name: String!
module_domain: String
number_of_topics_covered: Int!
learners_enrolled: [Learner!]!

type Learner {
first_name: String!
last_name: String!
username: String!

Learner is not anything different from EducationModule in terms of how it is defined. It does contain different fields, but it is just a GraphQL shape that can be used like any other shape.

💡 For this to work, you will want to define both shapes inside the same GraphQL file when writing ComposeDB schemas.


Directives are keywords that help add validation rules to a scalar. Not all scalars need to have directives, though Strings are required to have a maxLength. Let’s add directives to the two shapes used in this guide:

type EducationModule {
module_name: String! @string(maxLength: 50)
module_domain: String @string(minLength: 5, maxLength: 50)
number_of_topics_covered: Int! @int(min: 1, max: 100)
learners_enrolled: [Learner!]! @list(maxLength: 30)

type Learner {
first_name: String! @string(minLength: 10, maxLength: 30)
last_name: String! @string(maxLength: 30)
username: String! @string(maxLength: 32)


  • Each directive is declared using the @ symbol
  • @string adds validation rules to values that are strings, e.g. minimum and maximum length
  • @int adds validation rules to values that are integers, e.g. minimum and maximum values
  • @list adds validation rules to an array, e.g. maximum length

Next Steps

Learn how to add Relations to your schema