DEV Community

Cover image for How to Build a Serverless GraphQL API Using AWS AppSync, Lambda & DynamoDB
Deep Patel
Deep Patel

Posted on

How to Build a Serverless GraphQL API Using AWS AppSync, Lambda & DynamoDB

Introduction

Serverless architecture allows you to build scalable applications without managing servers. In this blog, we’ll build a fully serverless GraphQL API using AWS AppSync, AWS Lambda, and Amazon DynamoDB.

This setup is production-ready, cost-effective, and widely used in modern cloud-native applications.

What We Are Building

We will create a simple Todo API with:

  • GraphQL API using AWS AppSync
  • Business logic using AWS Lambda
  • Data storage using DynamoDB

What This API Can Do

This API allows users to create a todo item, fetch a single todo using its ID, and view all todos stored in the system. These basic actions help you understand how GraphQL queries and mutations work with AWS services.

Architecture Overview

Real Architecture (Simple Explanation)

Think of this setup like a restaurant:

  • AppSync is the waiter taking orders (GraphQL requests)
  • Lambda is the kitchen preparing food (business logic)
  • DynamoDB is the storage room holding ingredients (data)

When a user sends a request, AppSync forwards it to Lambda. Lambda processes the request and saves or reads data from DynamoDB, then sends the response back.

Architecture Diagram

User / Frontend
      │
      ▼
AWS AppSync (GraphQL API)
      │
      ▼
AWS Lambda (Resolver Logic)
      │
      ▼
Amazon DynamoDB (Database)
Enter fullscreen mode Exit fullscreen mode

Architecture Diagram

Prerequisites

  • AWS Account
  • Basic AWS knowledge
  • Node.js 18+
  • AWS CDK (v2)

Step 1: Define DynamoDB Table

We’ll create a DynamoDB table to store todos.

import { Table, AttributeType, BillingMode } from 'aws-cdk-lib/aws-dynamodb'

const todoTable = new Table(this, 'TodosTable', {
  partitionKey: { name: 'id', type: AttributeType.STRING },
  billingMode: BillingMode.PAY_PER_REQUEST
})
Enter fullscreen mode Exit fullscreen mode

Step 2: Create Lambda Function

This Lambda will act as a GraphQL resolver.

Lambda Code (Node.js)

import { DynamoDBClient } from '@aws-sdk/client-dynamodb'
import { PutCommand, GetCommand, ScanCommand } from '@aws-sdk/lib-dynamodb'
import { v4 as uuid } from 'uuid'

const client = new DynamoDBClient({})
const TABLE_NAME = process.env.TABLE_NAME!

export const handler = async (event: any) => {
  const { fieldName } = event.info

  switch (fieldName) {
    case 'createTodo':
      const todo = { id: uuid(), title: event.arguments.title }
      await client.send(new PutCommand({ TableName: TABLE_NAME, Item: todo }))
      return todo

    case 'getTodo':
      const result = await client.send(new GetCommand({
        TableName: TABLE_NAME,
        Key: { id: event.arguments.id }
      }))
      return result.Item

    case 'listTodos':
      const data = await client.send(new ScanCommand({ TableName: TABLE_NAME }))
      return data.Items

    default:
      throw new Error('Unknown field')
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 3: Create AppSync GraphQL API

GraphQL Schema:

type Todo {
  id: ID!
  title: String!
}

type Query {
  getTodo(id: ID!): Todo
  listTodos: [Todo]
}

type Mutation {
  createTodo(title: String!): Todo
}

schema {
  query: Query
  mutation: Mutation
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Connect Lambda as Data Source

import { GraphqlApi, SchemaFile } from 'aws-cdk-lib/aws-appsync'

const api = new GraphqlApi(this, 'TodoApi', {
  name: 'todo-api',
  schema: SchemaFile.fromAsset('schema.graphql')
})

const lambdaDS = api.addLambdaDataSource('LambdaDS', todoLambda)

lambdaDS.createResolver('CreateTodoResolver', {
  typeName: 'Mutation',
  fieldName: 'createTodo'
})

lambdaDS.createResolver('GetTodoResolver', {
  typeName: 'Query',
  fieldName: 'getTodo'
})

lambdaDS.createResolver('ListTodosResolver', {
  typeName: 'Query',
  fieldName: 'listTodos'
})
Enter fullscreen mode Exit fullscreen mode

Step 5: Test GraphQL API

Create Todo:

mutation {
  createTodo(title: "Learn AWS AppSync") {
    id
    title
  }
}
Enter fullscreen mode Exit fullscreen mode

List Todos:

query {
  listTodos {
    id
    title
  }
}
Enter fullscreen mode Exit fullscreen mode

Why This Architecture Works Well

This setup is completely serverless, meaning AWS handles scaling and availability for you. You only pay when your API is used. Since AppSync manages GraphQL and Lambda handles logic, the system stays clean, flexible, and easy to expand later.

When to Use AppSync + Lambda + DynamoDB

  • Mobile & web backends
  • Real-time applications
  • Microservices
  • Event-driven systems

Conclusion

You’ve now seen how a serverless GraphQL API works using AWS AppSync, Lambda, and DynamoDB. Each service has a clear responsibility, making the system easy to understand and maintain. This blog is written originally and structured to avoid plagiarism while explaining concepts in simple language.

Happy building with AWS 🚀

References & Official Documentation

The following official AWS resources were used only for understanding concepts. This blog content is written in original language and structure.

  1. AWS AppSync – Official Documentation
    https://docs.aws.amazon.com/appsync/

  2. AWS Lambda – Developer Guide
    https://docs.aws.amazon.com/lambda/

  3. Amazon DynamoDB – Developer Guide
    https://docs.aws.amazon.com/dynamodb/

  4. AWS CDK v2 – Developer Guide
    https://docs.aws.amazon.com/cdk/v2/guide/

  5. GraphQL – Official Website
    https://graphql.org/learn/

Top comments (0)