Configuration Reference
Configuration File
The configuration file (default: appsync-config.json) defines your GraphQL API:
| Property | Type | Required | Description |
|---|---|---|---|
schema | string | string[] | Yes | Path to GraphQL schema file(s) |
port | number | No | Server port (default: 4000) |
apiConfig | object | No | API configuration including auth |
dataSources | array | Yes | Data source definitions |
resolvers | array | Yes | Resolver mappings |
Path Resolution
All file paths in the config are resolved relative to the config file's directory:
my-project/
├── appsync-config.json
├── schema.graphql
└── resolvers/
└── getUser.js
// appsync-config.json
{
"schema": "./schema.graphql", // ✓ Relative to config file
"resolvers": [{
"file": "./resolvers/getUser.js" // ✓ Relative to config file
}]
}
Authentication
Configure authentication in apiConfig.auth:
API Key
{
"type": "API_KEY",
"key": "da2-your-api-key",
"expiration": 1735689600000 // Optional: Unix timestamp
}
AWS Lambda Authorizer
With local Lambda file:
{
"type": "AWS_LAMBDA",
"lambdaFunction": "auth/authorizer.js"
}
With mock identity (for local development without a Lambda):
{
"type": "AWS_LAMBDA",
"identity": {
"sub": "user-123",
"username": "testuser",
"groups": ["admin", "users"]
},
"resolverContext": {
"tenantId": "tenant-abc",
"role": "admin"
}
}
The identity fields are available in resolvers via ctx.identity:
ctx.identity.sub- User IDctx.identity.username- Usernamectx.identity.groups- User groups array
The resolverContext is available via ctx.identity.resolverContext.
Cognito User Pools
{
"type": "AMAZON_COGNITO_USER_POOLS",
"userPoolId": "us-east-1_xxxxx"
}
OpenID Connect
{
"type": "OPENID_CONNECT",
"issuer": "https://your-issuer.com",
"clientId": "your-client-id"
}
IAM
{
"type": "AWS_IAM"
}
Multiple Auth Methods
Configure multiple auth methods. The first one that succeeds will be used:
{
"apiConfig": {
"auth": [
{ "type": "AWS_LAMBDA", "identity": { "sub": "dev-user" } },
{ "type": "API_KEY", "key": "fallback-key" }
]
}
}
Using @aws-appsync/utils
Write resolvers exactly as you would for AWS AppSync. Standard imports work seamlessly:
import { util } from '@aws-appsync/utils';
import { put } from '@aws-appsync/utils/dynamodb';
export function request(ctx) {
return put({
key: { id: util.autoId() },
item: { ...ctx.arguments.input, createdAt: util.time.nowISO8601() }
});
}
export function response(ctx) {
return ctx.prev.result;
}
The same resolver code works locally and when deployed to AWS AppSync.
Global Utilities
util, runtime, and extensions are also available as globals (no import needed):
export function request(ctx) {
return { id: util.autoId(), timestamp: util.time.nowEpochSeconds() };
}
DynamoDB Helpers
Available from @aws-appsync/utils/dynamodb:
get(),put(),update(),remove()- Single item operationsquery(),scan()- Query and scan operationsbatchGet(),batchPut(),batchDelete()- Batch operationstransactGet(),transactWrite()- Transactionsoperations- Update builders (increment,append, etc.)
Resolver Configuration
Each resolver maps a GraphQL field to a data source:
Unit Resolver
{
"type": "Query",
"field": "getUser",
"kind": "Unit",
"dataSource": "UsersTable",
"file": "./resolvers/getUser.js"
}
Pipeline Resolver
{
"type": "Mutation",
"field": "createOrder",
"kind": "Pipeline",
"file": "./resolvers/createOrder.js",
"pipelineFunctions": [
{
"dataSource": "UsersTable",
"file": "./functions/validateUser.js"
},
{
"dataSource": "OrdersTable",
"file": "./functions/createOrder.js"
}
]
}
Schema Directives
appsync-local fully supports AWS AppSync authorization directives for field-level access control.
Authorization Directives
Control which auth modes can access types and fields:
| Directive | Description |
|---|---|
@aws_api_key | Allow API key authentication |
@aws_iam | Allow IAM authentication |
@aws_cognito_user_pools | Allow Cognito User Pools authentication |
@aws_oidc | Allow OpenID Connect authentication |
@aws_lambda | Allow Lambda authorizer authentication |
Type-Level Authorization
Apply directives to entire types - all fields inherit the auth requirements:
type Query @aws_api_key @aws_cognito_user_pools {
getPublicData: String # Both API key and Cognito can access
listItems: [Item] # Both API key and Cognito can access
}
Field-Level Authorization
Override type-level directives for specific fields:
type Query @aws_api_key {
publicData: String # Inherits @aws_api_key from type
adminData: String @aws_iam # Only IAM users can access
}
Cognito Group Restrictions
Restrict access to specific Cognito groups:
type Mutation {
updateUser: User @aws_cognito_user_pools
deleteUser: User @aws_cognito_user_pools(cognito_groups: ["Admin"])
}
Subscription Directives
Link subscriptions to mutations using @aws_subscribe:
type Subscription {
onPostCreated: Post @aws_subscribe(mutations: ["createPost"])
onPostUpdated: Post @aws_subscribe(mutations: ["updatePost", "editPost"])
}
Lambda Authorizer Dynamic Denial
Lambda authorizers can dynamically deny specific fields by returning deniedFields:
// auth/authorizer.js
export async function handler(event) {
const user = validateToken(event.authorizationToken);
return {
isAuthorized: true,
deniedFields: user.role === 'basic'
? ['Query.premiumContent', 'Mutation.adminAction']
: [],
resolverContext: { userId: user.id, role: user.role }
};
}
CLI Options
appsync-local start [options]
Options:
-c, --config <path> Config file path (default: appsync-config.json)
-p, --port <number> Server port (overrides config)
-h, --help Show help
Environment Variables
| Variable | Description |
|---|---|
PORT | Server port (if not specified in config or CLI) |
APPSYNC_LOCAL_SSL_REJECT_UNAUTHORIZED | Set to "false" to allow self-signed SSL certs for RDS |