Build a Production-ready GraphQL API Using StepZen’s Declarative Approach

Lucia Cerchie - Apr 1 '22 - - Dev Community

Originally posted by Lucia Cerchie on StepZen's blog

“The code you write to create the API is approximately the code you need to write to run, manage and maintain that API.” — Why StepZen

Deploying a GraphQL API to production means taking careful consideration of how you handle certain aspects of your API: pagination, performance, and security. It also means having a plan for how you manage changes; the addition and manipulation of your data sources.

With StepZen, the code that you write to create a GraphQL API amounts to the code you write to run and manage your API in production. Parallelism is built-in, pagination is configurable, and adding or changing backends, parameters, queries, and mutations is a matter of slipping in a custom directive. The endpoints are protected with an API key by default, and JWT-based protection is configurable. Schemas and resolvers are autogenerated for you, so you don’t have to write them. And as a result, StepZen provides built-in performance optimizations. Let’s take a deeper look at this schema-based approach to readying your API for production.

Speed Up Response Time

Swift response time is paramount for any production-ready API. In the internal processing of a GraphQL request, a single request can call multiple backends. StepZen’s service is aware of which of those backend requests can be made in parallel, and which are dependent on other requests. That means StepZen automatically parallelizes the execution of a query when possible, which speeds up response time.

Adding and Changing Backends

Before you deploy a GraphQL API to production, you want to connect your backends according to the demands of your data sources, but you also want to be able to change and add backends after you’ve deployed to production, in case the needs of your frontend change, or if you have a new CMS or database to integrate. To connect a new backend with StepZen you can run a single command from the StepZen CLI. For example, to add a REST backend, you’d run:

stepzen import curl "https://introspection.apis.stepzen.com/customers"
Enter fullscreen mode Exit fullscreen mode

You can copy-paste this command and try it out on your machine, if you like! Provided you’ve signed up for StepZen and downloaded the CLI. This command introspects the REST endpoint and generates a schema for you. In the schema, you can see queries written in this manner:

type Query {
  myQuery: RootEntry
    @rest(
      endpoint: "https://introspection.apis.stepzen.com/customers"
      headers: [{ name: "Content-Type", value: "$Content-Type;" }]
      configuration: "json_introspection_config"
    )
}
Enter fullscreen mode Exit fullscreen mode

As you can see, inside the introspected schema, a custom directive @rest points StepZen at the REST endpoint, as well as setting the header and configuration details through the corresponding arguments. In this manner, StepZen connects to the REST endpoint, eliminating the task of writing resolvers.

To connect another data source, such as a SQL or NoSQL database, or even another GraphQL API, you’d use a stepzen import command as well. As is the case with stepzen import curl, StepZen introspects the database backends and autogenerates the schemas and resolvers for you. The schemas generated by these commands will include custom @dbquery and @graphql directives that connect to the backends from within the schema.

You can combine data from multiple endpoints with another of StepZen’s directives, @materializer. Here’s an example of @materializer in action:

type GetCustomer {
  address: Address
  email: String
  id: Int
  name: String
  orders: [Order]
    @materializer(
      query: "getOrderListByCustomerId"
      arguments: [{ name: "customerId", field: "id" }]
    )
}
Enter fullscreen mode Exit fullscreen mode

Here, @materializer is feeding results from a query to a separate database into the GetCustomer type. Again, no resolvers are necessary.

Configurable Pagination

Production-ready APIs include pagination where necessary. You can configure pagination on a REST API on your terms by adding a pagination argument to a @rest directive. The type determines the type of pagination (page number, offset, or cursor) and the setters value determine the total number of results/pages.

 type Query {
  getPaginatedCustomerList(first: Int!, after: Int!): CustomerConnection
    @rest(
      endpoint: "https://introspection.apis.stepzen.com/customers?limit=$first&offset=$after"
      pagination: {
        type: PAGE_NUMBER
        setters: [{ field: "total", path: "total_pages" }]
      }
    )
}
Enter fullscreen mode Exit fullscreen mode

Endpoint Protection

In other methods of deploying GraphQL APIs, you often have to bring in separate libraries like graphql-shield to protect your API properly for production. With StepZen, the endpoints are protected with an API key by default. If you’d like to add JWT-based protection, you can add code like this to your configuration file.

deployment:
  identity:
    keys:
      - algorithm: HS256
        key: my-little-secret

[... other configuration]

- rootoperationtype: Query
  privatefieldspredicate: "?jwt"
Enter fullscreen mode Exit fullscreen mode

To learn how to add authorization as well, you can take a look at StepZen’s docs.

Where to Go From Here

In conclusion, StepZen is a solid choice for creating your GraphQL API in terms of pagination and adding and connecting backends, but also for maintaining it, in terms of parallelism for performance and endpoint protection. StepZen’s custom directives and convenient CLI tooling make the process of getting your GraphQL API into shape for production smooth.

If you have questions about getting started with StepZen, consult our docs. Or hop into Discord, we’d love to see you there.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .