Skip to content
All essays
ArchitectureJanuary 18, 202512 min

GraphQL API Development Guide: Modern API Architecture

Master GraphQL API development with Node.js. Learn schema design, resolvers, queries, mutations, and best practices.

Ü
Ümit Uz
Mobile & Full Stack Developer

What is GraphQL?

GraphQL is a query language for APIs that allows clients to request exactly the data they need, nothing more.

Basic Schema

graphql
type User {
  id: ID!
  name: String!
  email: String!
  posts: [Post!]!
}

type Post {
  id: ID!
  title: String!
  content: String!
  author: User!
}

type Query {
  user(id: ID!): User
  users: [User!]!
  posts: [Post!]!
}

type Mutation {
  createUser(name: String!, email: String!): User!
  createPost(title: String!, content: String!, authorId: ID!): Post!
}

Setting Up with Apollo Server

javascript
import { ApolloServer } from '@apollo/server';
import { startStandaloneServer } from '@apollo/server/standalone';

const typeDefs = `#graphql
  type User {
    id: ID!
    name: String!
    email: String!
  }

  type Query {
    users: [User!]!
    user(id: ID!): User
  }
`;

const resolvers = {
  Query: {
    users: () => [],
    user: (_, { id }) => findById(id)
  }
};

const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server);
console.log(`🚀 Server ready at ${url}`);

Queries

Fetch Data

graphql
query {
  users {
    id
    name
    email
  }
}

query GetUser($id: ID!) {
  user(id: $id) {
    id
    name
  }
}

Mutations

Modify Data

graphql
mutation CreateUser($name: String!, $email: String!) {
  createUser(name: $name, email: $email) {
    id
    name
    email
  }
}

Best Practices

  1. 1Use specific types: Avoid overly generic types
  2. 2Handle errors gracefully: Return partial results when possible
  3. 3Use pagination: Implement cursor-based pagination
  4. 4Optimize resolvers: Use DataLoader to prevent N+1 queries
  5. 5Validate inputs: Use schema validation

Error Handling

javascript
const resolvers = {
  Query: {
    user: async (_, { id }, { dataSources }) => {
      try {
        return await dataSources.userAPI.getUserById(id);
      } catch (error) {
        throw new GraphQLError(error.message, {
          extensions: {
            code: 'USER_NOT_FOUND',
            http: { status: 404 }
          }
        });
      }
    }
  }
};

Conclusion

GraphQL provides a flexible and efficient alternative to REST. Use it when you need complex data fetching and real-time updates.

Related essays

Next essay
REST API Design Best Practices: Building Robust APIs