Skip to content
Santekno.com | Tech Tutorials and Trends
EN
📖 0%
04 Oct 2025 · 5 min read ·Article 96 / 125
Go

96 Migrating a REST API to GraphQL

IH
Ihsan Arif
Writer at Santekno · Backend Engineer

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 products
  • GET /products/:id — Fetches product details, including the merchant data

REST API Structure

http
1GET /products

Response:

json
1[
2  {
3    "id": "1",
4    "name": "T-Shirt",
5    "merchant_id": "42"
6  },
7  // ...
8]
http
1GET /merchants/42

Response:

json
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:

MERMAID
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.

MERMAID
graph TD
    A[REST API] -->|Routing| D[API Gateway]
    B[GraphQL Server] -->|Routing| D
    D -->|Client Request| C[Frontend]
  • An API Gateway can route /graphql requests 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

graphql
 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.

js
 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

RESTGraphQL
Request Count2 (product + merchant)1
Response SizeOften overfetch/underfetchMatches query needs
Schema EvolutionRequires versioningField-level deprecation supported
CachingPer resource/endpointUsually done per query

Example GraphQL Query:

graphql
1query {
2  product(id: "1") {
3    name
4    merchant {
5      name
6      address
7    }
8  }
9}

Sample Response:

json
 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! 🚀

Related Articles

💬 Comments