Skip to content

GraphQL Complete Guide: Schema-Driven API Design from Scratch

In this tutorial, you'll learn about GraphQL Complete Guide: Schema. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.

GraphQL is a query language and runtime for APIs that lets clients request exactly the data they need, eliminating over-fetching and under-fetching common in REST.

What You'll Learn

  • GraphQL core concepts: schema, queries, mutations, resolvers
  • The type system: objects, scalars, enums, and relationships
  • Writing queries with arguments, aliases, and fragments
  • Mutations for creating, updating, and deleting data
  • Architecture patterns and tooling (GraphiQL, Apollo)

Why GraphQL Matters

REST APIs force fixed response structures. To get a user and their posts, you typically need two requests (GET /users/1, GET /users/1/posts). GraphQL lets you fetch both in one request, specifying exactly the fields you need. DodaTech's Durga Antivirus Pro dashboard uses GraphQL to fetch device details, scan history, and threat alerts in a single query — each UI component specifies its data needs without backend changes.

flowchart LR
    A["Client App"] -->|"Single Query"| B["GraphQL API\n(You are here)"]
    B --> C["Type Definitions\n(Schema)"]
    B --> D["Resolvers"]
    D --> E["Database"]
    D --> F["REST APIs"]
    D --> G["External\nServices"]
    style B fill:#dbeafe,stroke:#2563eb
    style C fill:#fef3c7,stroke:#d97706
    style D fill:#dcfce7,stroke:#16a34a
â„šī¸ Info

Prerequisites: Familiarity with REST concepts. JavaScript knowledge helpful for the examples.

GraphQL vs REST

Aspect REST GraphQL
Data fetching Fixed endpoints Client-specified
Over-fetching Common (get entire resource) Never (request only what you need)
Under-fetching Common (multiple endpoints needed) Never (one request, nested data)
Versioning URI versioning (/v1/users) No versioning — evolve schema
Caching Built-in HTTP caching Manual (Apollo cache, Relay)
File upload Native (multipart) Requires additional config
Learning curve Lower Higher (schema, resolvers, tooling)
Best for Public APIs, simple CRUD Complex UIs, dashboards, mobile apps

Core GraphQL Concepts

Schema Definition Language (SDL)

GraphQL APIs are defined by a schema written in SDL:

type Device {
  id: ID!
  name: String!
  os: String!
  lastScan: DateTime
  threats: [Threat!]!
}

type Threat {
  id: ID!
  name: String!
  severity: Severity!
  detectedAt: DateTime!
}

enum Severity {
  LOW
  MEDIUM
  HIGH
  CRITICAL
}

type Query {
  device(id: ID!): Device
  threats(severity: Severity): [Threat!]!
  devices: [Device!]!
}

type Mutation {
  createDevice(name: String!, os: String!): Device!
  deleteDevice(id: ID!): Boolean!
}

Queries (Read Data)

# Request
query GetCriticalThreats {
  threats(severity: CRITICAL) {
    id
    name
    detectedAt
  }
}

# Response
{
  "data": {
    "threats": [
      { "id": "th-001", "name": "Emotet", "detectedAt": "2026-06-06T10:00:00Z" }
    ]
  }
}

Mutations (Write Data)

# Request
mutation CreateNewDevice {
  createDevice(name: "Office-PC", os: "Windows 11") {
    id
    name
    os
  }
}

# Response
{
  "data": {
    "createDevice": {
      "id": "dev-007",
      "name": "Office-PC",
      "os": "<a href="/operating-systems/windows/">Windows</a> 11"
    }
  }
}

Common Mistakes

1. Exposing Database Schema Directly

GraphQL types should reflect your API contract, not your database tables. Map database columns to meaningful GraphQL fields with proper naming.

2. N+1 Query Problem

Without data loaders, each nested field resolver makes a separate database query:

query { devices { threats { name } } }
// N=100 devices → 1 query for devices + 100 queries for threats = 101 queries

Use DataLoader to batch and cache database queries.

3. Ignoring Depth Limits

Malicious clients can craft deeply nested queries that overload your server. Implement query depth limits and complexity analysis.

4. Not Using Fragments

Repeating the same field selections in multiple queries is error-prone. Use fragments to reuse field selections.

5. Forgetting That Every Field Has a Resolver

If a field doesn't have an explicit resolver, GraphQL defaults to looking for a property with the same name on the parent object. This is convenient but can cause unexpected null errors.

Practice Questions

  1. What is the main advantage of GraphQL over REST?
  2. What problem does the N+1 query problem cause?
  3. What is the difference between a Query and a Mutation?
  4. Why doesn't GraphQL need versioning?
  5. What is the purpose of DataLoader?

Answers:

  1. Clients specify exactly what data they need in a single request — no over-fetching or under-fetching.
  2. N+1 causes excessive database queries (1 parent query + N child queries), slowing down response times. DataLoader batches child queries into single queries.
  3. Queries fetch data (parallel, cached), Mutations modify data (sequential, side effects).
  4. You can add new fields and types without breaking existing queries. Clients only request what they need, so new fields don't affect them.
  5. DataLoader batches and caches database queries to solve the N+1 Problem, grouping many individual lookups into batch requests.

Challenge: Write a GraphQL schema for Durga Antivirus Pro with types for User, Device, Threat, and Scan. Include queries for fetching a user's devices and their latest threats, and a mutation for submitting a new threat report.

FAQ

Is GraphQL faster than REST?

: GraphQL reduces round trips (one request instead of many) and eliminates over-fetching (less data transferred). But it adds server-side processing overhead for schema validation and resolver execution. For complex UIs with nested data, GraphQL is often faster. For simple CRUD, REST may be faster.

Can I use GraphQL with an existing REST API?

: Yes — resolvers can call REST APIs as data sources. Apollo Server supports RESTDataSource for wrapping REST endpoints. This lets you add a GraphQL layer on top of existing REST services.

Does GraphQL replace databases?

: No — GraphQL is an API layer, not a database. It sits between clients and your data sources (databases, REST APIs, Microservices). You still need a database to store and query data.

What is the GraphQL schema?

: The schema is the contract between client and server. It defines all available types, queries, mutations, and their relationships. It's written in Schema Definition Language (SDL) and is the single source of truth for the API.

Try It Yourself

Explore a live GraphQL API using the public SpaceX API:

curl -X POST https://api.spacex.land/graphql \
  -H "Content-Type: application/json" \
  -d '{ "query": "query { launches(limit: 3) { mission_name launch_date_utc } }" }'

You get back exactly mission_name and launch_date_utc — no extra fields, no multiple endpoints.

What's Next

Topic Description
Types & Schema Design Define your schema with objects, enums, and relationships
Queries & Resolvers Write queries and resolver functions
Mutations Guide Create, update, and delete data
RESTful APIs Compare GraphQL with REST for different use cases
âŦ… RESTful APIs Guide
➡ GraphQL Introduction

Published Topics

GraphQL Introduction Explained: Schema, Queries & Resolvers for Beginners

Learn GraphQL from scratch: schema definition, queries with arguments, resolver functions, the GraphiQL IDE, and how GraphQL improves on REST API patterns.

✓ Live

GraphQL Types & Schema Design — Complete Guide with SDL Examples

Master GraphQL type system: objects, scalars, enums, interfaces, unions, input types, and schema design patterns for clean, maintainable GraphQL APIs.

✓ Live

GraphQL Queries & Resolvers Explained: Arguments, Context & Data Fetching

Master GraphQL queries and resolvers: query arguments, resolver chain, context for auth/database, DataLoader batching, and pagination patterns with examples.

✓ Live

GraphQL Mutations Guide: Create, Update & Delete Data with Input Types

Master GraphQL mutations: defining mutations with input types, modifying data with resolvers, error handling patterns, and comparing mutations with RESTful POST/PUT/DELETE.

✓ Live

GraphQL Architecture Guide: Server Setup, Subscriptions & Apollo Federation

Learn GraphQL architecture: Apollo Server setup, subscriptions for real-time data, schema federation for microservices, security patterns, and production best practices.

✓ Live

GraphQL API Reference & Cheatsheet — Schema, Queries, Mutations Quick Guide

Complete GraphQL reference: type system syntax, query structure, resolver patterns, Apollo Server config, subscription setup, common schemas, and error handling.

✓ Live

GraphQL SDL (Schema Definition Language) — Complete Syntax Guide

Master GraphQL Schema Definition Language (SDL): type definitions, field syntax, directives, comments, and schema organization patterns for designing clean GraphQL APIs.

✓ Live

GraphQL Scalars — Custom Scalar Types Explained

Master GraphQL custom scalars: implementing serialization, parsing, and validation for DateTime, JSON, Email, URL, and domain-specific scalar types with Apollo Server.

✓ Live

GraphQL Enums — Fixed Value Sets for Type-Safe APIs

Master GraphQL enums: defining enum types, using them in schemas and queries, implementing resolvers with enum validation, and best practices for enum design.

✓ Live

GraphQL Interfaces — Shared Field Contracts Across Types

Master GraphQL interfaces: defining shared fields, implementing types, using inline fragments for type-specific fields, and designing polymorphic schemas.

✓ Live

GraphQL Unions — Polymorphic Return Types Without Shared Fields

Master GraphQL union types: defining unions, resolving concrete types, querying with inline fragments, and choosing between unions and interfaces.

✓ Live

GraphQL Interface Type — Complete Guide

Learn how GraphQL interface types define shared fields across multiple object types, enabling polymorphic queries and consistent data modeling in schemas.

✓ Live

GraphQL Input Types — Structured Mutation Arguments Explained

Master GraphQL input types: defining reusable input objects for mutations and arguments, validation patterns, input type best practices, and designing clean mutation APIs.

✓ Live

GraphQL Union Type — Complete Guide

Learn how GraphQL union types represent a set of object types without shared fields, allowing flexible responses when the exact return type is unknown.

✓ Live

GraphQL Arguments — Query and Field Arguments Explained

Master GraphQL arguments: passing arguments to queries, mutations, and individual fields, required vs optional, default patterns, and complex argument structures.

✓ Live

GraphQL Enum Type — Complete Guide

Learn how GraphQL enum types restrict fields to predefined string values, enforcing data integrity and improving schema documentation clarity for API consumers.

✓ Live

GraphQL Directives — Schema and Query Annotations Explained

Master GraphQL directives: built-in directives like @deprecated, @skip, and @include, creating custom directives for auth and formatting, and directive patterns.

✓ Live

GraphQL Input Type — Complete Guide

Learn how GraphQL input types define structured argument objects for mutations and queries, enabling complex nested input validation in a single operation.

✓ Live

GraphQL Subscriptions Deep Dive — Real-Time Data with WebSockets

Master GraphQL subscriptions for real-time data: WebSocket transport, subscription resolvers, Redis Pub/Sub, filtering, authentication, and production patterns.

✓ Live

GraphQL Custom Scalar — Complete Guide

Learn how GraphQL custom scalars extend the type system for domain values like dates, JSON, and URLs with tailored serialization and validation logic.

✓ Live

GraphQL Nested Resolvers — Resolver Chains and Data Fetching Patterns

Master GraphQL nested resolvers: resolver chains, parent argument, default resolvers, resolving relationships, and optimizing nested data fetching.

✓ Live

GraphQL Custom Directive — Complete Guide

Learn how GraphQL custom directives enable reusable annotations for schema transformations, authorization, and runtime behavior modifications across operations.

✓ Live

GraphQL DataLoader — Solving the N+1 Problem with Batching

Master GraphQL DataLoader for solving the N+1 query problem: batch loading, caching, creating loaders for relationships, and production DataLoader patterns.

✓ Live

Advanced GraphQL Subscriptions — Complete Guide

Learn advanced GraphQL subscription patterns including event filtering, context propagation, back-pressure handling, and multi-tenant real-time data streaming.

✓ Live

GraphQL Batching — Grouping Operations for Performance

Master GraphQL batching strategies: query batching, mutation batching, DataLoader batching, persisted queries, and automatic persisted queries (APQ) for performance.

✓ Live

GraphQL Defer and Stream — Complete Guide

Learn how GraphQL defer and stream directives enable incremental data delivery, boosting performance by sending partial results before the full response.

✓ Live

GraphQL Error Handling — Error Patterns and Best Practices

Master GraphQL error handling: error types, partial success, Apollo Server errors, custom error codes, error masking in production, and client-side error handling.

✓ Live

GraphQL Live Query — Complete Guide

Learn how GraphQL live queries provide real-time data synchronization by re-executing queries on data changes and pushing updated results to subscribed clients.

✓ Live

GraphQL Authentication — Securing Your API with JWT and Context

Master GraphQL authentication: JWT token verification, context-based auth, directive-based auth guards, token refresh, and integrating with Auth0 and Firebase.

✓ Live

GraphQL Federation v2 — Complete Guide

Learn how GraphQL Federation v2 composes multiple subgraph services into a unified supergraph with improved entity resolution and type sharing across teams.

✓ Live

GraphQL Authorization — Role-Based Access Control Patterns

Master GraphQL authorization: role hierarchies, field-level permissions, directive-based auth, row-level security, and integrating with policy engines like CASL.

✓ Live

Apollo Router — Complete Guide

Learn how the Apollo Router provides a high-performance GraphQL gateway for federated services with caching, authentication, and request lifecycle management.

✓ Live

GraphQL Federation — Distributed GraphQL for Microservices

Master GraphQL Federation: splitting schemas across microservices, Apollo Gateway, subgraphs, entity references, and production federation patterns.

✓ Live

GraphQL Gateway Pattern — Complete Guide

Learn how the GraphQL gateway pattern unifies multiple backend services behind a single endpoint, enabling schema stitching and intelligent request routing.

✓ Live

GraphQL Apollo Server — Production Configuration and Deployment

Master Apollo Server for production: configuration options, plugins, caching, persisted queries, error handling, security, and deployment best practices.

✓ Live

GraphQL Batching Optimization — Complete Guide

Learn how GraphQL batching combines multiple queries or mutations into one request to reduce network overhead and improve overall API throughput performance.

✓ Live

GraphQL Express — Integrating GraphQL with Express.js

Master GraphQL-Express integration: apollo-server-express, middleware setup, combining REST endpoints, file uploads, and custom Express middleware with GraphQL.

✓ Live

GraphQL DataLoader — Complete Guide

Learn how DataLoader batches and caches database requests in GraphQL resolvers, eliminating N+1 query problems and optimizing data fetching performance.

✓ Live

GraphQL Code Generation — TypeScript Types from Schema

Master GraphQL Code Generator: generating TypeScript types from SDL, client-side operation types, React hooks, and custom codegen plugins and configuration.

✓ Live

GraphQL Testing — Unit, Integration and E2E Testing Strategies

Master GraphQL testing: unit testing resolvers, integration testing with Apollo Server, testing with mocked data, snapshot testing, and CI pipeline testing.

✓ Live

Solving REST Over-Fetching with GraphQL — Request Only What You Need

Learn how GraphQL solves REST API over-fetching by letting clients specify exact fields, reducing payload sizes, and improving API efficiency for mobile and web apps.

✓ Live

GraphQL Security — Depth Limiting, Cost Analysis, and Protection

Master GraphQL security: query depth limiting, cost analysis, rate limiting, introspection control, authentication, and protecting against malicious queries.

✓ Live

GraphQL Performance — Query Optimization, Caching and Best Practices

Master GraphQL performance optimization: response caching, DataLoader batching, query optimization, CDN caching with persisted queries, and performance monitoring.

✓ Live

GraphQL Under-Fetching — Solving the N+1 Problem with Batched Queries

Learn how GraphQL prevents under-fetching and the N+1 problem, allowing clients to request related data in a single query instead of multiple REST round-trips.

✓ Live

GraphQL Project — Build a Complete Full-Stack Application

Build a complete GraphQL-powered application: schema design, Apollo Server, React frontend with Apollo Client, authentication, real-time subscriptions, and deployment.

✓ Live

GraphQL Schema Definition Language — Defining Types, Fields, and Relationships

Master GraphQL SDL for defining object types, fields with arguments, relationships, scalars, enums, interfaces, and the core schema definition syntax.

✓ Live

GraphQL Object Types — Defining Structured Data with Fields and Relationships

Master GraphQL object types: defining structured data types with fields, relationships, arguments, resolvers, and best practices for organizing type definitions.

✓ Live

GraphQL Custom Scalar Types — Extending Primitives for Domain-Specific Values

Learn GraphQL custom scalar types: defining custom scalars for dates, URLs, JSON, and domain values, implementing parsing and serialization, and validation.

✓ Live

GraphQL Enum Types — Defining Fixed Sets of Allowed Values

Learn GraphQL enum types for defining fixed set of allowed values, enum value mapping, best practices for enum design, and type safety benefits.

✓ Live

GraphQL Interface Types — Defining Shared Fields Across Multiple Object Types

Learn GraphQL interface types for defining common fields across object types, implementing interfaces, querying with inline fragments, and design patterns.

✓ Live

GraphQL Union Types — Polymorphic Responses Without Shared Fields

Learn GraphQL union types for returning different object types from the same field, union vs interface comparison, and implementing __resolveType for unions.

✓ Live

GraphQL Input Types — Structured Arguments for Mutations and Queries

Master GraphQL input types for passing complex structured data as mutation and query arguments, input validation, nested inputs, and best practices.

✓ Live

GraphQL Arguments Deep Dive — Field-Level Parameters for Filtering and Pagination

Master GraphQL arguments on fields and queries: defining arguments, default values, input validation, and patterns for filtering, sorting, and pagination.

✓ Live

GraphQL Directives Deep Dive — @deprecated, @skip, @include, and Schema Metadata

Master GraphQL directives: built-in directives (@deprecated, @skip, @include), defining custom directives, directive locations, and use cases for schema annotations.

✓ Live

GraphQL Custom Directives — Building Reusable Schema Annotations and Middleware

Learn GraphQL custom directives for reusable schema behavior: authorization, rate limiting, caching, input validation, logging, and transforming field behavior.

✓ Live

GraphQL Nested Queries — Traversing Relationships with Resolver Chains

Learn GraphQL nested queries for traversing object relationships, resolver chains, performance optimization with DataLoader, and avoiding N+1 queries.

✓ Live

GraphQL Resolver Arguments — Accessing Query Parameters in Field Resolvers

Learn GraphQL resolver arguments: accessing query parameters, argument validation, default values, and patterns for passing arguments through resolver chains.

✓ Live

GraphQL Resolver Parent — Accessing the Parent Object in Resolver Chains

Learn GraphQL resolver parent parameter for accessing the parent object in resolver chains, transforming parent data, and optimizing nested field resolution.

✓ Live

GraphQL Resolver Context — Sharing Authentication, Database, and State Across Resolvers

Learn GraphQL resolver context for sharing authentication, database connections, loaders, and request-scoped state across all resolvers in a request.

✓ Live

GraphQL Mutation Return Types — Designing Payloads for Create, Update, and Delete Operations

Learn GraphQL mutation return types: designing meaningful payloads with returned data, errors, and status fields for reliable client-side mutation handling.

✓ Live

GraphQL Subscription Filtering — Sending Targeted Events to Specific Clients

Learn GraphQL subscription filtering for delivering targeted events to specific clients using arguments, context-based filtering, and multi-tenant event routing.

✓ Live

GraphQL Subscription Context — WebSocket Authentication for Real-Time Events

Learn GraphQL subscription context for WebSocket authentication, connection lifecycle, secure subscription initialization, and handling auth tokens in real-time connections.

✓ Live

GraphQL Pagination — Keyset, Offset, and Cursor-Based Pagination Explained

Master GraphQL pagination patterns: offset-based, cursor-based, and relay-style pagination with connections, edges, and page info for efficient data loading.

✓ Live

GraphQL Rate Limiting — Protect Your API from Abuse and Overuse

Learn GraphQL rate limiting strategies: query complexity analysis, depth limiting, per-user throttling, and integrating rate limiters with Apollo Server and Express.

✓ Live

GraphQL File Upload — Complete Guide with Apollo Server and Multipart Requests

Master GraphQL file uploads using the Upload scalar, multipart form data, streams, and validation. Implement file upload mutations with Apollo Server and Express.

✓ Live

GraphQL Cost Analysis — Query Complexity and Field Weighting for API Protection

Learn GraphQL cost analysis: assigning weights to fields, calculating query complexity, preventing expensive queries, and protecting your API from resource exhaustion.

✓ Live

GraphQL Caching Strategies — CDN, Resolver-Level, and Persisted Queries

Learn GraphQL caching: HTTP caching with GET requests, Apollo cache hints, DataLoader for batching, persisted queries, and CDN cache invalidation strategies.

✓ Live

GraphQL Subscriptions Client — Building Real-Time Features with WebSockets

Learn building GraphQL subscription clients: WebSocket connection lifecycle, reconnection, error handling, using Apollo Client with subscriptions, and real-time UI updates.

✓ Live

GraphQL Logging — Structured Logging, Tracing, and Error Tracking for APIs

Master GraphQL logging: structured logging for resolvers, Apollo Studio reporting, OpenTelemetry tracing, error tracking, and building audit trails for GraphQL operations.

✓ Live

GraphQL Monitoring — Metrics, Alerts, and Performance Dashboards for APIs

Learn GraphQL monitoring: tracking query performance, error rates, cache hit ratios, and resource usage with Prometheus, Grafana, Apollo Studio, and custom metrics.

✓ Live

All 70 topics in GraphQL Complete Guide: Schema-Driven API Design from Scratch are published.