96 Migrating a REST API to GraphQL
96 Migrating a REST API to GraphQL: A Complete Guide with a Case Study
Migrating from a REST API to GraphQL has become a trend among many companies that want to offer a more flexible and efficient API experience for frontend developers. This phenomenon is especially noticeable among startups that have high demands for rapid development and frequent UI/UX iteration. This article discusses the reasons, challenges, migration patterns, and best practices for transitioning from REST to GraphQL—along with a simple case study and an example implementation.
Why Migrate to GraphQL?
REST APIs have been the de-facto standard for more than a decade. However, several problems start to surface in real-world practice:
- Overfetching & Underfetching: REST APIs are usually structured around resources. Clients often fetch more or less data than they actually need.
- Many Roundtrips: Gathering data spread across several REST endpoints can require multiple requests just to render a single frontend screen.
- Slow API Evolution: Iterating on a REST API tends to be slower and more prone to breaking changes.
GraphQL solves these problems with a “query what you need” approach. Clients can fetch exactly the data they need in a single query, making the API more dynamic and easier to evolve.
Case Study: A Simple Migration from REST to GraphQL
Let’s take the example of a simple marketplace application with two main resources:
GET /products— Fetches the list of productsGET /products/:id— Fetches product details, including the merchant data
REST API Structure
1GET /productsResponse:
1[
2 {
3 "id": "1",
4 "name": "T-Shirt",
5 "merchant_id": "42"
6 },
7 // ...
8]1GET /merchants/42Response:
1{
2 "id": "42",
3 "name": "KaosMerah",
4 "address": "Jakarta"
5}To display the product details together with the merchant information on the frontend, the application needs to make multiple API calls:
sequenceDiagram
participant Client
participant REST_API
Client->>REST_API: GET /products/1
REST_API-->>Client: product detail (with merchant_id)
Client->>REST_API: GET /merchants/42
REST_API-->>Client: merchant detail
Migration Pattern: The Strangler Pattern
Migrating from REST to GraphQL should not be done all at once, in order to mitigate risk. One classic approach is the Strangler Pattern: build GraphQL alongside REST, then gradually move features over.
graph TD
A[REST API] -->|Routing| D[API Gateway]
B[GraphQL Server] -->|Routing| D
D -->|Client Request| C[Frontend]
- An API Gateway can route
/graphqlrequests to GraphQL and everything else to REST. - Gradually, REST features are moved over to GraphQL.
Implementation: An Example Endpoint Migration
1. Defining the GraphQL Schema
1type Product {
2 id: ID!
3 name: String!
4 merchant: Merchant!
5}
6
7type Merchant {
8 id: ID!
9 name: String!
10 address: String!
11}
12
13type Query {
14 product(id: ID!): Product
15 products: [Product!]!
16}2. A GraphQL Resolver That Calls REST
Early migrations often use schema stitching or a REST data source in GraphQL, so that the GraphQL backend merely acts as a proxy in front of REST.
1// Using Apollo Server in Node.js
2const { RESTDataSource } = require('apollo-datasource-rest');
3
4class ProductAPI extends RESTDataSource {
5 constructor() {
6 super();
7 this.baseURL = 'https://api.96market.com/';
8 }
9
10 async getProduct(id) {
11 return this.get(`products/${id}`);
12 }
13
14 async getProducts() {
15 return this.get('products');
16 }
17}
18
19class MerchantAPI extends RESTDataSource {
20 constructor() {
21 super();
22 this.baseURL = 'https://api.96market.com/';
23 }
24
25 async getMerchant(id) {
26 return this.get(`merchants/${id}`);
27 }
28}
29
30const resolvers = {
31 Query: {
32 product: async (_, { id }, { dataSources }) => {
33 const product = await dataSources.productAPI.getProduct(id);
34 // the merchant field will be loaded by the nested resolver
35 return product;
36 },
37 products: async (_, __, { dataSources }) => {
38 return dataSources.productAPI.getProducts();
39 }
40 },
41 Product: {
42 merchant: async (product, _, { dataSources }) => {
43 return dataSources.merchantAPI.getMerchant(product.merchant_id);
44 }
45 }
46};Efficiency Comparison: REST vs GraphQL Query
| REST | GraphQL | |
|---|---|---|
| Request Count | 2 (product + merchant) | 1 |
| Response Size | Often overfetch/underfetch | Matches query needs |
| Schema Evolution | Requires versioning | Field-level deprecation supported |
| Caching | Per resource/endpoint | Usually done per query |
Example GraphQL Query:
1query {
2 product(id: "1") {
3 name
4 merchant {
5 name
6 address
7 }
8 }
9}Sample Response:
1{
2 "data": {
3 "product": {
4 "name": "T-Shirt",
5 "merchant": {
6 "name": "KaosMerah",
7 "address": "Jakarta"
8 }
9 }
10 }
11}Migration Challenges and Tips
1. The N+1 Problem
GraphQL allows nested queries, but be careful about the “N+1 Problem.” Use a data loader to batch requests to the backend.
2. Authorization
REST APIs typically use resource-level permissions. In GraphQL, authorization needs to be considered all the way down to the field level if necessary.
3. Schema Evolution
GraphQL encourages backward compatibility through field deprecation, but schema management must be done with discipline.
4. Error Handling
REST usually relies on HTTP status codes. In GraphQL, error handling uses an array of errors in the JSON response. Structure your errors consistently.
5. Monitoring & Logging
Migrating to GraphQL requires good observability. Track which queries are requested most often, response times, and potential bottlenecks.
Conclusion
Migrating a REST API to GraphQL offers more efficient data transfer and greater flexibility for the frontend, but it does not come without challenges. Applying the Strangler Pattern, using a RESTDataSource early on, and maintaining discipline in schema evolution are the keys to a successful migration.
With a gradual approach like this, we can keep existing clients running while delivering a more modern and powerful API to new developers.
GraphQL is not a silver bullet—but for many use cases, especially those that require agility and rapid evolution, migrating from REST to GraphQL is one of the most strategic investments your engineering team can make in 2024.
References:
Interested in migrating or want to discuss further? Feel free to leave a comment below! 🚀