AppSync Diagnostics
When to use
Any AppSync investigation where the console alone is insufficient — resolver errors, schema deployment failures, authorization issues, subscription connection problems, caching misconfigurations, query latency, N+1 data fetching, or merged API conflicts.
Investigation workflow
Step 1 — Collect and triage
aws appsync list-graphql-apis
aws appsync get-graphql-api --api-id <api-id>
aws appsync list-resolvers --api-id <api-id> --type-name <type>
aws appsync list-data-sources --api-id <api-id>
aws appsync get-schema-creation-status --api-id <api-id>
aws appsync list-api-keys --api-id <api-id>
Step 2 — Domain deep dive
aws appsync get-resolver --api-id <api-id> --type-name <type> --field-name <field>
aws appsync get-data-source --api-id <api-id> --name <ds-name>
aws cloudwatch get-metric-statistics --namespace AWS/AppSync --metric-name 4XXError --dimensions Name=GraphQLAPIId,Value=<api-id> ...
aws cloudwatch get-metric-statistics --namespace AWS/AppSync --metric-name 5XXError --dimensions Name=GraphQLAPIId,Value=<api-id> ...
aws cloudwatch get-metric-statistics --namespace AWS/AppSync --metric-name Latency --dimensions Name=GraphQLAPIId,Value=<api-id> ...
aws appsync list-functions --api-id <api-id>
Read references/appsync-guardrails.md before concluding on any AppSync issue.
Tool quick reference
| Tool / API |
When to use |
list-graphql-apis |
List all APIs in the account/region |
get-graphql-api |
API config, auth modes, log settings, endpoints |
list-resolvers |
Resolvers for a given type |
get-resolver |
Resolver runtime, mapping templates, pipeline config |
list-data-sources |
All data sources attached to the API |
get-data-source |
Data source type, config, IAM role |
get-schema-creation-status |
Schema deployment status and errors |
list-api-keys |
API key expiration and status |
list-functions |
Pipeline functions for pipeline resolvers |
Gotchas: AppSync
- VTL mapping templates (Apache Velocity) vs JavaScript resolvers (APPSYNC_JS runtime) are two distinct resolver runtimes. VTL uses
$ctx and $util, JavaScript uses ctx and util — they are NOT interchangeable.
- Pipeline resolvers chain multiple functions (before → function1 → function2 → ... → after). Each function has its own request/response mapping. The
$ctx.stash (VTL) or ctx.stash (JS) passes data between functions.
- Resolver timeout is 30 seconds maximum. This cannot be increased. For long-running operations, use async patterns with DynamoDB or EventBridge.
- Subscriptions connect via WebSocket using the
wss:// endpoint (realtime endpoint). The connection URL is different from the GraphQL HTTP endpoint. Clients must use graphql-ws or Amplify libraries.
- Real-time subscriptions use MQTT over WebSocket protocol internally. Connection limits apply: 100 subscriptions per connection, connection idle timeout of 5 minutes without keepalive.
- Five authorization modes: API_KEY, AMAZON_COGNITO_USER_POOLS, AWS_IAM, OPENID_CONNECT, AWS_LAMBDA. Multiple auth modes can be configured on a single API with
@aws_auth directives.
- Caching TTL is configurable per API (1–3600 seconds). Per-resolver caching overrides API-level caching. Caching requires a dedicated cache instance (t2.small to r5.12xlarge) — it is NOT free.
- Conflict detection for offline/real-time sync: Versioned (optimistic concurrency), Automerge (automatic conflict resolution), Lambda (custom resolution logic). Only applies when using AppSync with DataStore/Amplify.
- Merged APIs combine multiple source APIs into a single endpoint. Schema conflicts between source APIs cause merge failures. Source API changes require re-merge.
- Batch resolvers (BatchInvoke for Lambda, BatchGetItem for DynamoDB) solve the N+1 problem. Without batching, a list query with N items triggers N individual resolver invocations.
Authorization mode comparison
| Mode |
Use Case |
Token Location |
Expiry |
| API_KEY |
Public/dev access |
x-api-key header |
Max 365 days |
| COGNITO |
User-based auth |
Authorization header (JWT) |
Token-based |
| IAM |
Service-to-service |
SigV4 signed request |
Session-based |
| OIDC |
External IdP |
Authorization header (JWT) |
Token-based |
| LAMBDA |
Custom auth logic |
Custom token header |
Per-request |
Anti-hallucination rules
- Always cite specific API configurations, resolver code, CloudWatch metrics, or error messages as evidence.
- VTL and JavaScript resolvers have completely different syntax and utilities. Never mix VTL
$util with JavaScript util or vice versa.
- Resolver timeout is hard-capped at 30 seconds. Never suggest increasing it beyond 30s.
- Subscription endpoints use
wss:// and are different from the GraphQL HTTPS endpoint. Never use the HTTP endpoint for subscriptions.
- Caching requires a provisioned cache instance with associated costs. Never claim caching is free or automatic.
- Spend no more than 2 minutes on any single hypothesis. Pivot if inconclusive.
26 runbooks
| Category |
IDs |
Covers |
| A — API |
A1–A3 |
API creation failures, schema errors, deployment issues |
| B — Resolvers |
B1–B4 |
VTL errors, JavaScript resolver errors, pipeline failures, timeout |
| C — Data Sources |
C1–C4 |
DynamoDB, Lambda, HTTP, RDS/Aurora data source errors |
| D — Auth |
D1–D3 |
API key issues, Cognito auth, IAM/OIDC auth |
| E — Subscriptions |
E1–E2 |
WebSocket connection failures, subscription filtering |
| F — Caching |
F1–F2 |
Cache configuration, cache invalidation |
| G — Performance |
G1–G2 |
Query latency, N+1 resolver issues |
| Z — Catch-All |
Z1 |
General troubleshooting |
1---2name: appsync-diagnostics3description: Use this skill to investigate and troubleshoot AWS AppSync problems (GraphQL APIs, merged APIs, real-time subscriptions) by analyzing API configurations, resolvers, data sources, authorization, and following structured runbooks. Activate when: schema errors, resolver failures, VTL mapping issues, JavaScript resolver errors, subscription disconnects, auth failures, caching problems, query latency, N+1 resolver issues, or the user says something is wrong with their AppSync API without naming specific symptoms.4---56# AppSync Diagnostics78## When to use910Any AppSync investigation where the console alone is insufficient — resolver errors, schema deployment failures, authorization issues, subscription connection problems, caching misconfigurations, query latency, N+1 data fetching, or merged API conflicts.1112## Investigation workflow1314### Step 1 — Collect and triage1516```17aws appsync list-graphql-apis18aws appsync get-graphql-api --api-id <api-id>19aws appsync list-resolvers --api-id <api-id> --type-name <type>20aws appsync list-data-sources --api-id <api-id>21aws appsync get-schema-creation-status --api-id <api-id>22aws appsync list-api-keys --api-id <api-id>23```2425### Step 2 — Domain deep dive2627```28aws appsync get-resolver --api-id <api-id> --type-name <type> --field-name <field>29aws appsync get-data-source --api-id <api-id> --name <ds-name>30aws cloudwatch get-metric-statistics --namespace AWS/AppSync --metric-name 4XXError --dimensions Name=GraphQLAPIId,Value=<api-id> ...31aws cloudwatch get-metric-statistics --namespace AWS/AppSync --metric-name 5XXError --dimensions Name=GraphQLAPIId,Value=<api-id> ...32aws cloudwatch get-metric-statistics --namespace AWS/AppSync --metric-name Latency --dimensions Name=GraphQLAPIId,Value=<api-id> ...33aws appsync list-functions --api-id <api-id>34```3536Read `references/appsync-guardrails.md` before concluding on any AppSync issue.3738## Tool quick reference3940| Tool / API | When to use |41|------------|-------------|42| `list-graphql-apis` | List all APIs in the account/region |43| `get-graphql-api` | API config, auth modes, log settings, endpoints |44| `list-resolvers` | Resolvers for a given type |45| `get-resolver` | Resolver runtime, mapping templates, pipeline config |46| `list-data-sources` | All data sources attached to the API |47| `get-data-source` | Data source type, config, IAM role |48| `get-schema-creation-status` | Schema deployment status and errors |49| `list-api-keys` | API key expiration and status |50| `list-functions` | Pipeline functions for pipeline resolvers |5152## Gotchas: AppSync5354- VTL mapping templates (Apache Velocity) vs JavaScript resolvers (APPSYNC_JS runtime) are two distinct resolver runtimes. VTL uses `$ctx` and `$util`, JavaScript uses `ctx` and `util` — they are NOT interchangeable.55- Pipeline resolvers chain multiple functions (before → function1 → function2 → ... → after). Each function has its own request/response mapping. The `$ctx.stash` (VTL) or `ctx.stash` (JS) passes data between functions.56- Resolver timeout is 30 seconds maximum. This cannot be increased. For long-running operations, use async patterns with DynamoDB or EventBridge.57- Subscriptions connect via WebSocket using the `wss://` endpoint (realtime endpoint). The connection URL is different from the GraphQL HTTP endpoint. Clients must use `graphql-ws` or Amplify libraries.58- Real-time subscriptions use MQTT over WebSocket protocol internally. Connection limits apply: 100 subscriptions per connection, connection idle timeout of 5 minutes without keepalive.59- Five authorization modes: API_KEY, AMAZON_COGNITO_USER_POOLS, AWS_IAM, OPENID_CONNECT, AWS_LAMBDA. Multiple auth modes can be configured on a single API with `@aws_auth` directives.60- Caching TTL is configurable per API (1–3600 seconds). Per-resolver caching overrides API-level caching. Caching requires a dedicated cache instance (t2.small to r5.12xlarge) — it is NOT free.61- Conflict detection for offline/real-time sync: Versioned (optimistic concurrency), Automerge (automatic conflict resolution), Lambda (custom resolution logic). Only applies when using AppSync with DataStore/Amplify.62- Merged APIs combine multiple source APIs into a single endpoint. Schema conflicts between source APIs cause merge failures. Source API changes require re-merge.63- Batch resolvers (BatchInvoke for Lambda, BatchGetItem for DynamoDB) solve the N+1 problem. Without batching, a list query with N items triggers N individual resolver invocations.6465### Authorization mode comparison6667| Mode | Use Case | Token Location | Expiry |68|------|----------|---------------|--------|69| API_KEY | Public/dev access | `x-api-key` header | Max 365 days |70| COGNITO | User-based auth | `Authorization` header (JWT) | Token-based |71| IAM | Service-to-service | SigV4 signed request | Session-based |72| OIDC | External IdP | `Authorization` header (JWT) | Token-based |73| LAMBDA | Custom auth logic | Custom token header | Per-request |7475## Anti-hallucination rules76771. Always cite specific API configurations, resolver code, CloudWatch metrics, or error messages as evidence.782. VTL and JavaScript resolvers have completely different syntax and utilities. Never mix VTL `$util` with JavaScript `util` or vice versa.793. Resolver timeout is hard-capped at 30 seconds. Never suggest increasing it beyond 30s.804. Subscription endpoints use `wss://` and are different from the GraphQL HTTPS endpoint. Never use the HTTP endpoint for subscriptions.815. Caching requires a provisioned cache instance with associated costs. Never claim caching is free or automatic.826. Spend no more than 2 minutes on any single hypothesis. Pivot if inconclusive.8384## 26 runbooks8586| Category | IDs | Covers |87|----------|-----|--------|88| A — API | A1–A3 | API creation failures, schema errors, deployment issues |89| B — Resolvers | B1–B4 | VTL errors, JavaScript resolver errors, pipeline failures, timeout |90| C — Data Sources | C1–C4 | DynamoDB, Lambda, HTTP, RDS/Aurora data source errors |91| D — Auth | D1–D3 | API key issues, Cognito auth, IAM/OIDC auth |92| E — Subscriptions | E1–E2 | WebSocket connection failures, subscription filtering |93| F — Caching | F1–F2 | Cache configuration, cache invalidation |94| G — Performance | G1–G2 | Query latency, N+1 resolver issues |95| Z — Catch-All | Z1 | General troubleshooting |