Logo
Home

Intuit Tech Stories: the GraphQL journey

As you can imagine, income tax season is a busy time for Intuit. It’s also a peak period for our GraphQL ecosystem, which processes up to two billion requests per day that time of year—or 37,000 requests per second. In our last blog, we explored the reasons developers might choose GraphQL APIs over REST. Now we’ll zoom in on Intuit’s own decision to use the protocol, describe how we implemented it, and offer a few tips for your own GraphQL journey.

Two types of traffic—two protocols

Intuit began using GraphQL in 2017, two years after it was open-sourced by Facebook. Our initial approach involved analyzing the different types of communication within our infrastructure to determine the most suitable protocols for each.

Like many organizations, Intuit’s network traffic can be broadly categorized along two axes:

  • North-south: This includes inbound communications from customer-facing clients accessing our API gateway, as well as outbound communications from the API gateway to external systems such as payment processors and data providers.
  • East-west: This refers to internal communications among our various microservices, databases, and other resources through internal or private APIs

We recognized that these distinct traffic patterns had different requirements and could be best served by different protocols.

GraphQL for north-south traffic

Our goal is to empower our consumers with as much autonomy as possible by effectively exposing our domain data. We found that a well-defined GraphQL API achieves this by making the entire data structure readily available to users. This eliminates the need for repeated requests to add attributes one by one, freeing up our backend developers to focus on other critical projects.

REST for east-west traffic

The internal communications between our services follow well-established and predictable paths. We had already built these using REST APIs and the gRPC framework, and these systems handled an extremely high volume of authorization and authorization decisions—often tens of millions per day. This demanded a high degree of stability and reliability. While we could have used GraphQL here, there wasn’t a compelling reason to switch, so we’ve maintained the existing REST and gRPC approach.

Subgraphs and supergraphs

For a smaller organization, a single GraphQL API instance might be plenty. Intuit is a very large organization, and we have many instances for different teams. In this scenario, each individual GraphQL API is referred to as a subgraph. When several of these subgraphs are joined together through federation or schema-stitching, you get a supergraph. This structure is transparent to users, who don’t need to worry about which subgraph is which.

If one supergraph is good, would multiple supergraphs be better? They can be, if they’re managed carefully. In our case, we decided to create a central GraphQL schema registry. That helps us identify any duplicates among our subgraphs—functionalities provided by two different APIs—and maintain a common set of tagged APIs that can be extracted for various use cases. This gives us the best of both worlds: multiple subgraphs that can be combined to create multiple supergraphs, with tagging and deduplication strategies to keep it all manageable.

Migrating from REST

Switching from REST to GraphQL involves a steep learning curve for both producers and consumers. With a lot of REST and gRPC in place, we needed to follow a careful migration strategy. At a high level, here’s the approach we used.

  1. Break the API layer from the service layer: To ensure a clear separation of concerns, move all the business logic from the REST API layer into the service layer. This architectural change helps to keep your API layers lean and focused on data presentation.
  2. Introduce the GraphQL API layer: Since you’ve already abstracted your business logic into the service layer, you can now expose it via the API gateway and make it part of your GraphQL supergraph.
  3. Phase out REST: Migrate your REST APIs completely to GraphQL APIs backed by your service layer.

Tools

Although GraphQL is relatively new and the available tools and libraries are limited, the following can be highly useful.

  • Mocking: GraphQL is strongly typed. That means you can define schema, mark responses, and generate output to validate your attributes and structure with consumers, and get their feedback early in the process, without having to write any code.
  • Postman: Postman’s GraphQL support lets you expose the GraphQL schema to introspection so you can identify which fields are available and construct queries to document your APIs.
  • GraphiQL: This IDE lets you explore, document, query, and run your available mutations using a graphical interface.
  • Netflix DGS. Netflix uses this graphical framework to build its own GraphQL architecture.
  • graphql-schema-linter: As individual teams start defining their own schema, it’s essential to ensure consistency in naming conventions and other practices across your subgraphs and supergraphs.
  • Intuit graph-quilt: We built this tool to create a unified graph that aggregates and combines multiple GraphQL APIs.

Best practices

As you’re starting with GraphQL APIs, keep these tips in mind.

  • Pay attention to error handling: When an error occurs in a REST API request, an HTTP status code like 404 or 500 provides immediate context for easy debugging. GraphQL is transport agnostic, so it doesn’t rely on HTTP-specific features like status codes. As a result, it almost always responds with a 200 HTTP status even if there’s an error, with any error details buried in the response body. Keep that in mind for error handling, observability, and monitoring.
  • Follow OWASP: Their GraphQL Cheat Sheet provides a great baseline for you to supplement with your own security guidelines.
  • Don’t autogenerate your schema: This could expose things you didn’t intend to, and it’s not very user-friendly. Take the time to understand your use cases and design your schema accordingly.
  • Disable introspection in production: Your GraphQL schema represents your API’s infrastructure. Disabling introspection in production prevents unauthorized users from exploring your entire schema.
  • Don’t expose your subgraphs to users: Remember that subgraphs are part of your internal infrastructure. Always present a unified view of your APIs through well-defined supergraphs.
  • Perform authorization at the service layer: Centralizing authorization logic at the service layer helps to keep your API layers lightweight, performant, and easier to manage.

Today, Intuit has over one hundred subgraphs constructed into supergraphs, and they’re accessed by about 2,000 clients. That may sound like a lot, but that two billion requests per day stat we mentioned earlier only represents about two percent of our total API traffic. We’re still relatively early in our GraphQL journey, but we’re excited about what we’ve already achieved—and about what’s still to come.

You can learn more about GraphQL and our experience with it in our Intuit Tech Stories session: From Basics to Best Practices: Why Developers Should Adopt GraphQL.


Contributing authors include Jared Cheney and Lucy Shen.


Posted

in

, ,

by

Tags: