# GraphQL 101: From Basics to Advanced

GraphQL is a query language for APIs and a runtime for executing those queries. It provides a complete and understandable description of the data in your API, empowering clients to request only the data they need and nothing more.

## **Why Use GraphQL?**

GraphQL was created to solve common issues with REST APIs, such as **over-fetching**, **under-fetching**, and **multiple network requests**. Unlike REST, which requires multiple API calls to obtain related data, GraphQL can fetch exactly what is needed in a single request.

### **Key Benefits:**

* **Efficient Data Fetching**: Clients can request only the required fields, reducing unnecessary data transfer.
    
* **Single Endpoint**: Unlike REST APIs, which often have multiple endpoints, GraphQL provides a single endpoint (`/graphql`).
    
* **Strongly Typed Schema**: GraphQL APIs are **schema-driven**, reducing the chances of errors.
    
* **Real-time Updates**: GraphQL supports **subscriptions**, allowing real-time data fetching.
    
* **Better Developer Experience**: The self-documenting schema makes it easier to understand and use APIs.
    

---

## **GraphQL vs. REST API**

GraphQL is often compared to REST, but it offers more flexibility. Here's a comparison:

| Feature | GraphQL | REST |
| --- | --- | --- |
| **Data Fetching** | Fetches only required data | Often over-fetches or under-fetches |
| **Endpoints** | Single endpoint (`/graphql`) | Multiple endpoints per resource |
| **Typing** | Strongly typed schema | No enforced schema |
| **Real-time Support** | Built-in subscriptions | Requires WebSockets or polling |
| **Performance** | Less network overhead | Higher overhead with multiple requests |

### **Example:**

Fetching user and their posts:

**REST API (Multiple Calls)**

1. `GET /user/1` → Fetch user details
    
2. `GET /user/1/posts` → Fetch posts separately
    

**GraphQL (Single Query)**

```graphql
query {
  user(id: "1") {
    name
    posts {
      title
      content
    }
  }
}
```

This makes GraphQL **faster** and **more efficient**.

---

## **Setting Up a GraphQL Server**

To build a GraphQL server, we need a **GraphQL schema** and **resolvers** to handle queries.

### **Step 1: Install Dependencies**

Using Apollo Server (Node.js example):

```bash
npm install apollo-server graphql
```

### **Step 2: Define the Schema**

The schema defines the structure of the API.

```graphql
type Query {
  hello: String
}
```

### **Step 3: Create Resolvers**

Resolvers return the data requested in the query.

```javascript
const resolvers = {
  Query: {
    hello: () => 'Hello, GraphQL!',
  },
};
```

### **Step 4: Start the Server**

```javascript
const { ApolloServer, gql } = require('apollo-server');

const server = new ApolloServer({ typeDefs, resolvers });

server.listen().then(({ url }) => {
  console.log(`Server ready at ${url}`);
});
```

This starts a **GraphQL API** that can be queried at [`http://localhost:4000`](http://localhost:4000).

---

## **Queries**

A **query** is a request to fetch data from a GraphQL server.

### **Example Query**

```graphql
query {
  user(id: "1") {
    name
    email
  }
}
```

**Schema Definition:**

```graphql
type Query {
  user(id: ID!): User
}

type User {
  id: ID!
  name: String
  email: String
}
```

**Resolver:**

```javascript
const resolvers = {
  Query: {
    user: (_, { id }) => users.find(user => user.id === id),
  },
};
```

This returns **only the requested fields**, making it efficient.

---

## **Mutations**

A **mutation** is used to **modify** data (create, update, delete records).

### **Example Mutation**

```graphql
mutation {
  createUser(name: "Alice", email: "alice@example.com") {
    id
    name
  }
}
```

**Schema:**

```graphql
type Mutation {
  createUser(name: String!, email: String!): User
}
```

**Resolver:**

```javascript
Mutation: {
  createUser: (_, { name, email }) => {
    const newUser = { id: users.length + 1, name, email };
    users.push(newUser);
    return newUser;
  },
};
```

This allows clients to **modify data easily**.

---

## **Subscriptions**

Subscriptions allow **real-time updates** by pushing data to clients when an event occurs.

### **Example Subscription**

```graphql
subscription {
  userCreated {
    id
    name
  }
}
```

**Schema:**

```graphql
type Subscription {
  userCreated: User
}
```

**Resolver with PubSub:**

```javascript
const { PubSub } = require('graphql-subscriptions');
const pubsub = new PubSub();

const resolvers = {
  Subscription: {
    userCreated: {
      subscribe: () => pubsub.asyncIterator(['USER_CREATED']),
    },
  },
  Mutation: {
    createUser: (_, { name, email }) => {
      const newUser = { id: users.length + 1, name, email };
      users.push(newUser);
      pubsub.publish('USER_CREATED', { userCreated: newUser });
      return newUser;
    },
  },
};
```

When a new user is created, all **subscribed clients get updated automatically**.

---

## **Directives**

Directives are special **annotations** in GraphQL that modify query execution.

### **Example: @deprecated Directive**

```graphql
type Query {
  oldField: String @deprecated(reason: "Use newField instead")
  newField: String
}
```

This **warns developers** when they use `oldField`.

---

## **Caching in GraphQL**

GraphQL doesn’t provide **built-in caching**, but tools like **Apollo Server** offer caching mechanisms.

### **Example: Apollo Cache**

```javascript
const server = new ApolloServer({
  typeDefs,
  resolvers,
  cache: "bounded",
});
```

This optimizes **performance** by reducing repeated database queries.

---

## **GraphQL Status Codes**

GraphQL responses always return a `200 OK` status code at the HTTP level, even for errors. Instead of relying on HTTP status codes for error handling, GraphQL includes a `errors` field in the response body.

#### Example Response with Errors:

```plaintext
{
  "errors": [
    {
      "message": "User not found",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["user"]
    }
  ],
  "data": {
    "user": null
  }
}
```

This approach ensures consistent response formats, making it easier for clients to handle errors.

For handling authentication or other specific cases, middleware can be used to return appropriate HTTP status codes before executing the GraphQL query.

---

## **GraphQL Playground**

GraphQL Playground is an **interactive tool** for testing queries.

### **Key Features**

* **Auto-completion**: Suggests queries based on schema.
    
* **Schema Documentation**: Helps explore API structure.
    
* **Query History**: Stores previously executed queries.
    
* **Real-time Subscriptions**: Allows subscription testing.
    

### **Enable Playground in Apollo Server**

```javascript
const server = new ApolloServer({
  typeDefs,
  resolvers,
  introspection: true, 
  playground: true,
});
```

Available at [`http://localhost:4000`](http://localhost:4000).

---

## **GraphQL Code Generation**

GraphQL Codegen **automates** the creation of strongly typed GraphQL code.

### **Installation**

```bash
npm install @graphql-codegen/cli
```

### **Configuration**

```yaml
schema: "http://localhost:4000/graphql"
generates:
  src/generated/graphql.ts:
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typescript-resolvers"
```

### **Run Codegen**

```bash
npx graphql-codegen
```

This helps in **generating types and queries automatically**.

### Advanced Concepts

1. **Batching and Caching with DataLoader**: DataLoader optimizes queries by batching and caching requests.
    
2. **Custom Scalars**: Define custom types like `Date`.
    
3. **Authentication and Authorization**: Use middleware to handle authentication.
    

---

GraphQL provides unparalleled flexibility and power for building APIs. Developers can build robust, scalable, and efficient applications by understanding their fundamentals and leveraging advanced features. It is a powerful alternative to REST, offering flexibility, efficiency, and real-time capabilities.  

## **👋 Enjoyed this blog?**

Reach out in the comments below or on [**LinkedIn**](https://www.linkedin.com/in/aakanksha-bhende/) to let me know what you think of it.

For more updates, do follow me [**here**](https://blogs.aakanksha.is-a.dev/) :)
