Configuration Reference

Configuration File

The configuration file (default: appsync-config.json) defines your GraphQL API:

PropertyTypeRequiredDescription
schemastring | string[]YesPath to GraphQL schema file(s)
portnumberNoServer port (default: 4000)
apiConfigobjectNoAPI configuration including auth
dataSourcesarrayYesData source definitions
resolversarrayYesResolver 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:

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:

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:

DirectiveDescription
@aws_api_keyAllow API key authentication
@aws_iamAllow IAM authentication
@aws_cognito_user_poolsAllow Cognito User Pools authentication
@aws_oidcAllow OpenID Connect authentication
@aws_lambdaAllow 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

VariableDescription
PORTServer port (if not specified in config or CLI)
APPSYNC_LOCAL_SSL_REJECT_UNAUTHORIZEDSet to "false" to allow self-signed SSL certs for RDS