Join us on Nov 7 for GraphQL Summit Virtual
Join API innovators, GraphQL experts, and AI trailblazers on Nov 7 at GraphQL Summit Virtual. Register for free →
This article answers common questions about GraphQL, organized by phases in the GraphQL adoption timeline.
After reading through the GraphQL basics, you understand how GraphQL works and its benefits. You're trying to create a proof of concept for your project or company to test GraphQL's viability in production.
If you need a refresher on GraphQL servers, check out How does a GraphQL server work?
There are GraphQL server tools available for most popular languages. Use the one(s) that best fit with your existing stack. If you plan on using a federated architecture, check out the list of federation-compatible server libraries.
One of the best things about GraphQL is that it works excellently with existing APIs. You can connect any number of existing services to your schema.
The most common source is a REST API. In the Apollo Server library, for example, the RESTDataSource
class integrates with Apollo Server to simplify fetching and caching for existing REST APIs. However, you can connect any backend to a schema. Resolvers can do anything, including fetch data from an SDK or ORM.
Many federation-compatible server libraries offer similar capabilities.
Schemas should be designed with the client's needs in mind. Rather than modeling queries and types after the underlying services, they should be designed to make querying as easy as possible. GraphQL's resolver structure allows this flexibility without many performance consequences.
The GraphQL community offers a rich ecosystem of client tooling. Apollo provides the following open-source, industry-standard SDKs:
As with any service, tracking errors and their causes is important. Many kinds of errors can occur in a GraphQL implementation. Some of these include service errors, where the schema can't access underlying data sources, and user errors, where a user enters invalid information in a query or mutation.
GraphQL is resilient to some of these errors. Because the schema is strongly typed, you can restrict what types of data users can provide as input, along with what types your resolvers can return. This type system catches many errors and requires no manual checks.
For errors not prevented by the type system, it's helpful to know what exact queries were made and with what variables. The Apollo GraphOS platform includes analytics tooling that does exactly this. It can help discover and reproduce errors by showing the exact conditions in which the error occurred.
After a successful proof of concept, the next step is to ensure your GraphQL service is ready for the demands of a production environment.
Public APIs of any kind need some safeguards against malicious queries. Since GraphQL allows for recursive queries, it wouldn't be hard to create an overly complicated query that acts as a DoS attack, even by accident. There are multiple ways to prevent something like this, from complexity limiting to query depth limiting. Read Apollo's security blog post to learn more.
Authentication and authorization are important topics to discuss with any API. GraphQL provides a granular approach to handling these topics. But don't worry; if an API being consumed by GraphQL already has authorization built-in, it may be possible to ignore it completely.
GraphQL can be cached in multiple places.
On the client, caches can prevent multiple queries from being called when data is already available locally. Client caches for GraphQL have one significant advantage over REST client caches: they can handle queries that have never been made. This is possible because of how GraphQL responses are normalized and stored.
For example, if a client requests a list of fruits, each fruit is cached separately on the client. Later, if the client requests a single fruit in a different query and the needed fruit is in the cache, the request doesn't have to use the network. This normalized cache is a part of apollo-client
by default.
You can also set up server-side caching, including whole-query caching, partial-query caching, and cache backed by a CDN. These can lower response times and make your GraphQL server as performant as possible.
Whole-query and CDN caches are most useful when an API handles multiple identical queries. This commonly happens with public data, like content on pages of a site. Whether the API is used for public data or not, these caches almost always provide large performance benefits and are highly recommended. See Server-side caching to learn about whole-query and CDN caching with Apollo Server.
Partial query caching can be achieved by caching the responses from underlying services with something like Redis or Memcache. With this strategy, even if two queries look completely different from one another, if there is any duplication of data fetched, those results can be shared, preventing unnecessary traffic. The RESTDataSource
does this automatically if the appropriate cache-control
headers are present in REST responses.
Many apps and sites are powered almost completely by an API such as a GraphQL schema, so it's important to ensure your service is always stable. Indicators of an unhealthy service include long response times, high resource usage, and unusual traffic patterns.
GraphOS Studio is a great tool for tracking many of these things. It allows close inspection of fields, making it easy to see total response times and how long each field took to execute.
GraphOS Studio also has some integrations to make monitoring easier. Notifications can deliver daily reports to give teams a quick overview of graph's health. The Datadog integration works with existing Datadog accounts to help teams track schema performance. Finally, you can configure the GraphOS Router to export telemetry metrics to your APM of choice.
You've decided to use GraphQL in production. You don't want to immediately refactor the APIs or apps. You want to move a single feature over to GraphQL to learn how to use and monitor it in production.
As with any large change, the adoption of GraphQL should be incremental. GraphQL allows teams to leave existing services as they are and build convenient gateways on top of them.
GraphQL schemas work best when their design is collaborated on by the combination of backend implementers and frontend consumers. It's tempting to design a schema to mirror underlying API structures or database tables, but this can reduce the usefulness of GraphQL.
You understand how to write, deploy, and monitor GraphQL in production and are looking to scale Its features to your entire product line.
Keeping all schema code together makes sense for smaller projects. However, once a project reaches a certain size or has many people working on it, it can be difficult to manage conflicts in the same file and code navigation.
This is when a federated architecture becomes imperative for scaling. Federation lets API teams operate in a microservices architecture while exposing a unified GraphQL API to clients.
Check out What is Federated Architecture to learn more.
Schemas naturally evolve over time. GraphQL schemas are more resilient to change than other APIs, but there are still occasions where breaking changes are necessary to support new functionality. GraphOS offers a suite of schema governance features, including schema checks, linting, and proposals, that let you manage, validate, and enforce standards in your schemas.
About
GraphQL.com is maintained by the Apollo team. Our goal is to give developers and technical leaders the tools they need to understand and adopt GraphQL.
GraphQL.com 2024