DVA-C02Chapter 30 of 101Objective 1.2

AWS AppSync and GraphQL APIs

This chapter covers AWS AppSync, a fully managed service that enables developers to build GraphQL APIs for their applications. For the DVA-C02 exam, AppSync appears in approximately 5-8% of questions, primarily in the Development domain (Objective 1.2: Develop APIs and integrations). You will need to understand how to define GraphQL schemas, configure resolvers to connect to data sources like DynamoDB and Lambda, implement real-time subscriptions, and manage authentication and authorization. Mastering AppSync is essential for building scalable, real-time, and flexible APIs in serverless architectures.

25 min read
Intermediate
Updated May 31, 2026

AppSync as a Smart Data Concierge

Imagine a large hotel with multiple departments: front desk, housekeeping, maintenance, and billing. Guests (client apps) want information from these departments, but they don't want to call each one separately or wait for slow responses. A smart concierge (AppSync) stands in the lobby with a whiteboard. Guests write their requests on sticky notes: 'I need my bill total AND my room service order status AND the gym hours.' The concierge takes the note, walks to each department, collects the answers, and returns with a single combined response. If a guest wants real-time updates—like when housekeeping finishes cleaning their room—the concierge gives them a pager that beeps instantly when the change happens. The concierge also checks permissions: only the guest themselves can see their bill, not other guests. Behind the scenes, the concierge has a map (schema) showing which departments have what information and how to ask for it (resolvers). This is exactly how AppSync works: it provides a single GraphQL endpoint that aggregates data from multiple sources (DynamoDB, Lambda, RDS, HTTP APIs), supports real-time subscriptions via WebSockets, enforces fine-grained access control, and uses a schema with resolvers to fetch and mutate data. Clients don't care about the backend complexity—they just talk to the concierge.

How It Actually Works

What is AWS AppSync?

AWS AppSync is a managed service that provides a GraphQL endpoint for applications. GraphQL is a query language for APIs that allows clients to request exactly the data they need, nothing more. Unlike REST, where multiple endpoints return fixed structures, GraphQL uses a single endpoint and a flexible query structure. AppSync handles the heavy lifting of parsing GraphQL queries, resolving them against backend data sources (DynamoDB, Lambda, Aurora, HTTP endpoints, Elasticsearch, and more), and returning results. It also supports real-time data via subscriptions (WebSockets) and offline data synchronization for mobile clients.

Why AppSync Exists

Traditional REST APIs often lead to over-fetching (getting too much data) or under-fetching (not enough data, requiring multiple calls). GraphQL solves this by letting clients specify their exact data requirements. However, building a production-grade GraphQL server requires significant effort: schema design, resolver logic, authentication, caching, real-time support, and scaling. AppSync abstracts all this, providing a fully managed GraphQL service with built-in security, monitoring, and scaling. For the DVA-C02 exam, you need to know that AppSync is the recommended AWS service for building GraphQL APIs, especially when combined with other serverless services.

How AppSync Works Internally

When a client sends a GraphQL request to an AppSync endpoint, the following steps occur:

1.

Request arrives at the AppSync endpoint. The endpoint is an HTTP(S) URL generated when you create the API. AppSync supports both queries and mutations over HTTP POST, and subscriptions over WebSocket.

2.

Authentication and Authorization. AppSync checks the request's authorization. It supports multiple auth modes: API_KEY, AWS_IAM, AMAZON_COGNITO_USER_POOLS, OPENID_CONNECT, and AWS_LAMBDA (custom authorizer). The auth mode is defined per API or per field. If authentication fails, AppSync returns an error.

3.

Schema Validation. AppSync validates the request against the GraphQL schema you defined. The schema defines types, queries, mutations, and subscriptions. If the query references fields that don't exist, AppSync returns a validation error.

4. Resolver Execution. For each field requested, AppSync invokes the associated resolver. A resolver is a bridge between the GraphQL field and a data source. Resolvers can be: - Unit resolvers (VTL templates): Use Apache Velocity Template Language (VTL) to transform requests and responses. VTL templates are written in a JSON-like syntax and can call AWS AppSync data sources. - Pipeline resolvers: A chain of functions (each with its own VTL template) that execute in sequence. Useful for complex operations like authorization checks before data fetch. - Lambda resolvers: Directly invoke a Lambda function. The function receives the GraphQL arguments and returns the result. This is the most flexible but also the most code-heavy.

5. Data Source Interaction. The resolver interacts with the configured data source. For example: - DynamoDB: The VTL template can perform GetItem, PutItem, Query, Scan, etc. AppSync supports DynamoDB as a direct data source without Lambda. - Lambda: The resolver invokes a Lambda function, passing the event payload. The function's response is returned as the field value. - HTTP: The resolver makes an HTTP request to any endpoint. - RDS (Aurora Serverless): AppSync can query Aurora Serverless via the Data API. - Elasticsearch: For full-text search. - EventBridge: To publish events.

6.

Response Assembly. AppSync collects all resolved field values and assembles the response JSON. If any resolver fails, AppSync may return partial data (depending on the nullability of fields) or an error.

7.

Real-time Subscriptions. If the client has an active subscription, AppSync maintains a WebSocket connection. When data changes (via a mutation), AppSync pushes the updated data to all subscribed clients. Subscriptions are defined in the schema and typically trigger on mutations.

Key Components, Values, Defaults, and Timers

- Schema: Written in GraphQL Schema Definition Language (SDL). Example:

type Todo {
    id: ID!
    name: String!
    completed: Boolean!
  }
  type Query {
    getTodo(id: ID!): Todo
    listTodos: [Todo]
  }
  type Mutation {
    createTodo(name: String!, completed: Boolean!): Todo
  }
  type Subscription {
    onTodoCreated: Todo
      @aws_subscribe(mutations: ["createTodo"])
  }
  schema {
    query: Query
    mutation: Mutation
    subscription: Subscription
  }

Note: @aws_subscribe directive marks a subscription field to trigger on specified mutations.

Data Sources: Each data source has a type (e.g., AMAZON_DYNAMODB_TABLE, AWS_LAMBDA, HTTP, RELATIONAL_DATABASE, ELASTICSEARCH, EVENT_BRIDGE). For DynamoDB, you specify the table name and region. For Lambda, you specify the function ARN.

Resolvers: Attached to fields. For each field, you can have a request mapping template and a response mapping template (VTL). For Lambda resolvers, you specify the function name and optionally a request/response mapping.

Caching: AppSync supports per-resolver caching with TTL from 1 second to 3600 seconds (1 hour). Default is no caching. Caching can reduce latency and cost.

Logging: AppSync can log to CloudWatch Logs. You can set the log level: NONE, ERROR, ALL.

X-Ray Tracing: AppSync integrates with AWS X-Ray to trace requests through resolvers and data sources.

API Key Expiration: API keys can have an expiration date. Default is 7 days, but can be set up to 365 days.

Subscription WebSocket: The WebSocket connection has a default timeout of 24 hours of inactivity. If no data is sent for 24 hours, the connection is closed.

Configuration and Verification Commands

You can manage AppSync via AWS Management Console, CLI, CloudFormation, CDK, or SDK. Common CLI commands:

# Create a GraphQL API
aws appsync create-graphql-api --name MyApi --authentication-type API_KEY

# Create an API key
aws appsync create-api-key --api-id <api-id>

# Create a data source
aws appsync create-data-source --api-id <api-id> --name TodoTable --type AMAZON_DYNAMODB_TABLE --dynamodb-config tableName=TodoTable,awsRegion=us-east-1

# Create a resolver
aws appsync create-resolver --api-id <api-id> --type-name Query --field-name getTodo --data-source-name TodoTable --request-mapping-template '{"version":"2017-02-28","operation":"GetItem","key":{"id":$util.dynamodb.toDynamoDBJson($ctx.args.id)}}' --response-mapping-template '$util.toJson($ctx.result)'

# Test a query
aws appsync evaluate-code --api-id <api-id> --type-name Query --field-name getTodo --code '{"version":"2017-02-28","operation":"GetItem","key":{"id":$util.dynamodb.toDynamoDBJson($ctx.args.id)}}' --context '{"arguments":{"id":"1"}}'

Interaction with Related Technologies

AWS Lambda: Often used as a resolver for complex business logic. The Lambda function receives an event with arguments, identity, source, request, and prev (for pipeline resolvers). The function must return a valid JSON response.

Amazon DynamoDB: AppSync can directly query DynamoDB, supporting all CRUD operations. It can also use DynamoDB Streams to trigger subscriptions.

Amazon Cognito: For user authentication and fine-grained access control. The identity object in resolvers contains Cognito claims.

AWS Step Functions: Can be used for long-running workflows triggered by AppSync mutations.

AWS WAF: Can be placed in front of AppSync to protect against common web exploits.

AWS CloudFront: Can be used as a CDN in front of AppSync for global distribution.

Walk-Through

1

Define GraphQL schema

Create a schema file (schema.graphql) that defines types, queries, mutations, and subscriptions. Use GraphQL SDL. Define all fields with types (String, Int, Float, Boolean, ID, custom types). Mark required fields with !. Use directives like @aws_subscribe for subscriptions. The schema is uploaded to AppSync via console, CLI, or CloudFormation. AppSync validates the schema upon upload. A well-defined schema is critical because it determines the API contract. For example, a schema with a Query type for getTodo and a Mutation type for createTodo, and a Subscription type for onTodoCreated. The schema must include at least one query type. Subscriptions are optional.

2

Configure authentication mode

Choose one or more authentication types for the API. Options: API_KEY (simple key-based, good for public endpoints), AWS_IAM (use IAM roles for access), AMAZON_COGNITO_USER_POOLS (Cognito user pools), OPENID_CONNECT (OIDC provider), AWS_LAMBDA (custom authorizer). You can set default auth mode and per-field auth overrides using @aws_auth or @aws_cognito_user_pools directives. For example, you might allow public read access with API_KEY but require Cognito for mutations. Configure this in the AppSync API settings. Authentication is enforced on every request. If using API_KEY, the key must be passed in the x-api-key header.

3

Add data sources

Create data sources that represent backend resources. For DynamoDB, specify the table name and region. For Lambda, specify the function ARN and optionally a service role ARN for AppSync to invoke the function. For HTTP, specify the endpoint URL and optional authorization. For RDS, specify the Aurora Serverless cluster ARN, database, and secret ARN. Each data source is given a name (e.g., TodoTable). You can have multiple data sources of the same type. AppSync uses IAM roles to access these resources securely. When creating a data source, AppSync will set up the necessary permissions if you provide a role with sufficient privileges.

4

Attach resolvers to fields

For each field in the schema that needs data from a backend, attach a resolver. Resolvers specify which data source to use and how to transform requests and responses. For unit resolvers, you provide VTL request and response mapping templates. For Lambda resolvers, you specify the function name and optionally mapping templates. For pipeline resolvers, you define a list of functions. The resolver is configured with the field name and type (Query, Mutation, Subscription). For example, attach a resolver to Query.getTodo that uses DynamoDB GetItem operation. The request template maps GraphQL arguments to DynamoDB key, and the response template converts DynamoDB output to GraphQL type.

5

Deploy and test API

Once schema, data sources, and resolvers are configured, the API is automatically deployed. You can test it using the AppSync console's Query editor, or via curl/Postman. For queries and mutations, send HTTP POST to the GraphQL endpoint with JSON body: {"query": "...", "variables": {...}}. For subscriptions, use a WebSocket client (e.g., wscat) to connect to the real-time endpoint. Use the API key or other auth mechanism. Monitor CloudWatch logs for errors. Verify that resolvers are returning expected data. For example, test a query: curl -X POST -H "x-api-key: $API_KEY" -H "Content-Type: application/graphql" --data '{ getTodo(id: "1") { id name completed } }' $ENDPOINT. Check that response contains the correct fields.

What This Looks Like on the Job

Enterprise Scenario 1: Real-Time Dashboard for IoT Data

A manufacturing company uses AppSync to power a real-time dashboard that displays sensor data from thousands of IoT devices. The backend stores sensor readings in DynamoDB. The GraphQL schema defines queries for historical data and subscriptions for real-time updates. When a new sensor reading is inserted via a mutation, a subscription triggers and pushes the data to all connected dashboard clients. The company uses AWS_IAM authentication because the dashboard runs on EC2 instances with IAM roles. They configured caching on historical queries to reduce DynamoDB reads. One common misconfiguration is setting the TTL too high, causing stale data to appear on the dashboard. They solved this by setting TTL to 30 seconds for the latest readings and no cache for real-time subscriptions. They also use X-Ray tracing to debug slow resolvers, discovering that a Lambda resolver was taking too long due to a cold start; they switched to a DynamoDB direct resolver for that field.

Enterprise Scenario 2: Mobile App with Offline Sync

A social media startup uses AppSync for its mobile app. Users can create posts, like, and comment. The app needs to work offline. AppSync's offline data synchronization uses AWS AppSync SDK for iOS/Android. The SDK caches data locally and syncs when connectivity is restored. The schema includes a @versioned directive for conflict resolution. When two users edit the same post offline, AppSync uses last-writer-wins or custom conflict resolution via a Lambda function. The authentication uses Amazon Cognito User Pools. Misconfiguration often occurs when developers forget to enable offline sync in the SDK or don't set up conflict resolution properly, leading to data loss. The startup also uses AppSync's Delta Sync to only transfer changed data, reducing bandwidth. They monitor the sync latency using CloudWatch metrics.

Enterprise Scenario 3: E-Commerce Product Catalog

An e-commerce company uses AppSync to serve product data to web and mobile clients. The product catalog is stored in Amazon Elasticsearch for full-text search. AppSync resolvers query Elasticsearch directly. The schema includes complex nested types like Product with variants and reviews. They use pipeline resolvers to first check if the user is authenticated (via a Lambda function) and then fetch data from Elasticsearch. They also use HTTP resolvers to call a legacy inventory service. A common issue is resolver timeout when Elasticsearch is slow; they set the resolver timeout to 10 seconds (default is 10s, max 30s). They also use API_KEY for public read access and Cognito for admin mutations. They learned to avoid overly deep nesting in queries because each level adds resolver calls, increasing latency.

How DVA-C02 Actually Tests This

What DVA-C02 Tests on AppSync

The DVA-C02 exam (Objective 1.2: Develop APIs and integrations) tests your ability to design and implement GraphQL APIs using AppSync. Specific areas include:

Defining GraphQL schemas (types, queries, mutations, subscriptions)

Configuring authentication (API_KEY, IAM, Cognito, OIDC, Lambda)

Attaching resolvers to data sources (DynamoDB, Lambda, HTTP)

Understanding VTL mapping templates (request/response)

Implementing real-time subscriptions

Enabling caching and offline sync

Integrating with other AWS services (Cognito, DynamoDB, Lambda, CloudWatch)

Common Wrong Answers and Why

1.

Choosing REST API Gateway over AppSync for a flexible query requirement: Candidates often select API Gateway because it's more familiar. However, if the requirement is that clients can request exactly the fields they need, GraphQL (AppSync) is the correct choice. The exam will describe a scenario where clients need to fetch multiple related resources in one request, and the answer is AppSync.

2.

Thinking AppSync requires Lambda for all data sources: AppSync can directly integrate with DynamoDB, HTTP, RDS, Elasticsearch, and EventBridge without Lambda. Candidates choose Lambda because they think it's necessary, but the exam tests knowledge of direct data source integrations.

3.

Confusing AppSync subscriptions with SNS/SQS: Subscriptions in AppSync are real-time WebSocket connections, not message queues. Candidates might incorrectly choose SNS for real-time updates, but the correct answer is AppSync subscriptions when the requirement is to push data to web/mobile clients.

4.

Misunderstanding authentication modes: Candidates may think API_KEY is secure for production. The exam tests that API_KEY is for development or public APIs, while Cognito or IAM is for production with user authentication.

Specific Numbers and Terms

Resolver timeout: 10 seconds default, max 30 seconds.

API key expiration: up to 365 days.

Caching TTL: 1 second to 3600 seconds.

WebSocket idle timeout: 24 hours.

VTL template version: 2017-02-28 or 2018-05-29.

Directives: @aws_subscribe, @aws_auth, @aws_cognito_user_pools, @aws_iam, @aws_lambda.

Data source types: AMAZON_DYNAMODB_TABLE, AWS_LAMBDA, HTTP, RELATIONAL_DATABASE, ELASTICSEARCH, EVENT_BRIDGE, NONE.

Edge Cases and Exceptions

Partial failures: If one resolver fails but the field is nullable, AppSync returns null for that field and an error in the errors array. If the field is non-nullable, the entire parent field becomes null.

Subscription filtering: Subscriptions can filter using arguments. For example, onTodoCreated(userId: String!) only triggers for that user.

Conflict resolution for offline sync: Use @versioned directive or custom Lambda.

Per-field authorization: Use directives to override default auth mode for specific fields.

How to Eliminate Wrong Answers

If the question mentions real-time updates to a web client, look for AppSync subscriptions, not polling or SNS.

If the question mentions a mobile app that needs offline support, look for AppSync with offline sync SDK.

If the question says 'clients can specify exactly the fields they need', it's GraphQL/AppSync.

If the question mentions caching with TTL, it's AppSync caching.

If the question mentions VTL templates, it's AppSync resolvers.

Eliminate choices that use REST API Gateway if the requirement is GraphQL.

Key Takeaways

AppSync is the AWS managed GraphQL service; use it when clients need flexible queries or real-time data.

Schema defines types, queries, mutations, subscriptions; use @aws_subscribe for subscription triggers.

Authentication modes: API_KEY (dev), IAM (services), Cognito (users), OIDC (external IdP), Lambda (custom).

Resolvers connect fields to data sources; can be unit (VTL), pipeline (multiple functions), or Lambda.

Direct data sources: DynamoDB, HTTP, RDS, Elasticsearch, EventBridge — no Lambda needed for simple operations.

Subscriptions use WebSockets; triggered by mutations; can filter by arguments.

Caching is per-resolver, TTL 1-3600 seconds, disabled by default.

Offline sync requires AppSync SDK; use @versioned directive or Lambda for conflict resolution.

Resolver timeout default 10s, max 30s; WebSocket idle timeout 24h.

Monitor with CloudWatch Logs and X-Ray tracing.

Easy to Mix Up

These come up on the exam all the time. Here's how to tell them apart.

AWS AppSync

Uses GraphQL: single endpoint, client specifies fields.

Built-in real-time subscriptions via WebSockets.

Supports offline data sync for mobile apps.

Direct integration with DynamoDB, Lambda, HTTP, RDS, Elasticsearch, EventBridge.

Uses resolvers with VTL templates for field-level data fetching.

Amazon API Gateway (REST)

Uses REST: multiple endpoints, fixed response structure.

No native real-time support; use WebSocket API or polling.

No built-in offline sync; requires custom solution.

Integrates with Lambda, HTTP, AWS services via proxy or integration.

Uses integration requests/responses with mapping templates (VTL) at the method level.

Watch Out for These

Mistake

AppSync only works with DynamoDB as a data source.

Correct

AppSync supports multiple data sources: DynamoDB, Lambda, HTTP, RDS (Aurora Serverless), Elasticsearch, EventBridge, and NONE (for static data). You can also use pipeline resolvers to combine multiple sources.

Mistake

AppSync requires you to write Lambda functions for every resolver.

Correct

AppSync can directly resolve fields using DynamoDB, HTTP, or other data sources without Lambda. Lambda is only needed for custom business logic. Direct resolvers use VTL templates.

Mistake

AppSync subscriptions are the same as Amazon SNS notifications.

Correct

AppSync subscriptions use WebSockets for real-time, bidirectional communication with clients. SNS is a pub/sub messaging service for decoupled services, not for direct client push. Subscriptions are triggered by mutations in AppSync.

Mistake

API_KEY authentication is secure for production use.

Correct

API_KEY provides only a simple key that can be easily shared or stolen. It is intended for development, testing, or public APIs where security is not a concern. For production, use IAM, Cognito, or OIDC.

Mistake

AppSync caches all data by default.

Correct

Caching is disabled by default. You must enable it per resolver and set a TTL. The default TTL is 0 (no cache). Caching is useful for read-heavy workloads but must be configured explicitly.

Do You Actually Know This?

Reveal each answer, then mark whether you got it right. Score 60%+ to unlock the next chapter.

Frequently Asked Questions

How do I set up real-time subscriptions in AppSync?

Define a subscription type in your schema with the @aws_subscribe directive specifying which mutations trigger it. For example: `type Subscription { onTodoCreated: Todo @aws_subscribe(mutations: ["createTodo"]) }`. Then, clients connect via WebSocket to the subscription endpoint. When a mutation like `createTodo` is performed, AppSync pushes the result to all subscribed clients. You can filter subscriptions by arguments, e.g., `onTodoCreated(userId: String!)`.

Can I use AppSync without a Lambda function?

Yes, AppSync can directly integrate with DynamoDB, HTTP, RDS, Elasticsearch, and EventBridge without Lambda. For example, you can create a DynamoDB data source and attach a resolver that performs GetItem, Query, or Scan using VTL templates. Lambda is only needed for custom logic that goes beyond simple CRUD operations.

What is the difference between a unit resolver and a pipeline resolver?

A unit resolver has a single request and response mapping template that interacts with one data source. A pipeline resolver consists of multiple functions (each with its own request/response mapping) that execute in sequence. Pipeline resolvers are useful for complex operations like authorization checks, data transformation, or calling multiple data sources in a specific order.

How does AppSync handle offline data synchronization?

AppSync provides client SDKs (iOS, Android, JavaScript) that cache data locally and sync when connectivity is restored. Use the `@versioned` directive in your schema to enable conflict detection. When a conflict occurs (e.g., two offline users edit the same field), you can configure AppSync to use last-writer-wins or a custom conflict resolution Lambda function.

What authentication method should I use for a public API?

For a public API where you want to allow anonymous access, use API_KEY authentication. However, API_KEY is not secure for production. For production public APIs, consider using Cognito User Pools with unauthenticated access (identity pools) or an OIDC provider. For internal services, use IAM authentication.

How do I debug slow resolvers in AppSync?

Enable CloudWatch Logs with log level ALL to see request/response details. Enable X-Ray tracing to see the end-to-end latency breakdown across resolvers and data sources. Use the AppSync console's Queries editor to test individual resolvers. Check resolver timeout settings (default 10s). If using Lambda, check Lambda cold starts and duration.

Can I use AppSync with an existing REST API?

Yes, you can create an HTTP data source that points to your REST API. AppSync resolvers can call that HTTP endpoint and transform the response. This allows you to gradually migrate from REST to GraphQL by wrapping existing APIs.

Terms Worth Knowing

Ready to put this to the test?

You've just covered AWS AppSync and GraphQL APIs — now see how well it sticks with free DVA-C02 practice questions. Full explanations included, no account needed.

Done with this chapter?