export const meta = {
  title: `Override Amplify-generated AppSync resources`,
  description: `The "amplify override api" command generates a developer-configurable "overrides" TypeScript file which provides Amplify-generated AppSync resources as CDK constructs. For example, developers can set api settings that are not directly available in the Amplify CLI workflow, such as X-Ray tracing.`,
};

```bash
amplify override api
```

Run the command above to override Amplify-generated GraphQL API resources including AWS AppSync API, Amazon DynamoDB table, Amazon OpenSearch domain, and more.

<Callout>

If you need to customize a specific Amplify-generated VTL resolver, review [Override Amplify-generated resolvers](/cli/graphql/custom-business-logic/#override-amplify-generated-resolvers) first.
</Callout>

The command creates a new `overrides.ts` file under `amplify/backend/api/<resource-name>/` which provides you the Amplify-generated resources as [CDK constructs](https://docs.aws.amazon.com/cdk/latest/guide/home.html).

## Customize Amplify-generated AppSync GraphQL API resources

Apply all the overrides in the `override(...)` function. For example to enable X-Ray tracing for the AppSync GraphQL API:

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.api.GraphQLAPI.xrayEnabled = true
}
```

You can override the following GraphQL API resources that Amplify generates:

|Amplify-generated resource|Description|
|-|-|
|[GraphQLAPI](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-graphqlapi.html)|AWS AppSync GraphQL API resource|
|[GraphQLAPIDefaultApiKey](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-apikey.html)|API Key resource for the AppSync GraphQL API|
|[GraphQLAPITransformerSchema](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-graphqlschema.html)|The GraphQL schema that's being deployed. (The output of the GraphQL Transformer)|
|[GraphQLAPINONEDS](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html)|A "none" data source that is used for requests that don't exit the AppSync API|
|[AmplifyDataStore](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)|The delta sync table used for Amplify DataStore's conflict resolution|
|[AmplifyDataStoreIAMRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|IAM role used to access the delta sync table for DataStore|
|[DynamoDBAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to access the DynamoDB resources from AppSync|

## Customize Amplify-generated resources for @model directive

Apply all the overrides in the `override(...)` function. Pass in the @model type name into `resources.models[...]` to modify the resources generated for that particular @model type. For example, to enable time-to-live on the Todo `@model` type's DynamoDB table:

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.models["Todo"].modelDDBTable.timeToLiveSpecification = {
    attributeName: "ttl",
    enabled: true
  }
}
```

You can override the following @model directive resources that Amplify generates:

|Amplify-generated resource|Description|
|-|-|
[modelStack](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html)|The nested stack containing all resources for the @model type|
[modelDDBTable](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html)|The DynamoDB table containing the data for this @model type|
[modelIamRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|IAM role to access the DynamoDB table for this @model type|
[modelIamRoleDefaultPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to access the delta sync table for this @model type in case DataStore is enabled|
[dynamoDBAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|Default policy associated with the IAM role to access the DynamoDB table for this @model type|
[modelDatasource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html)|The AppSync DataSource to representing the DynamoDB table|
[invokeLambdaFunction](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy for Lambda-based conflict resolution function|

For example, you can override a model generated DynamoDB table configuration. 

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.models["Todo"].modelDatasource.dynamoDbConfig['deltaSyncConfig']['baseTableTtl'] = '3600'
}
```
### Example - Configure DynamoDB table's billing mode

Set the [DynamoDB billing mode](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-billingmode) for the DynamoDB table. Either "PROVISIONED" or "PAY_PER_REQUEST".

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.models['Post'].modelDDBTable.billingMode = 'PAY_PER_REQUEST';
}
```
### Example - Configure provisioned throughput for DynamoDB table or Global Secondary Index
Override the default [ProvisionedThroughput](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-dynamodb-table.html#cfn-dynamodb-table-provisionedthroughput) provisioned for each `@model` table and its Global Secondary Indexes (GSI).

Only valid if the "DynamoDBBillingMode" is set to "PROVISIONED"

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.models['Post'].modelDDBTable.provisionedThroughput = {
    readCapacityUnits: 5,
    writeCapacityUnits: 5
  }
  
  /**
  * When billing mode is set to "PROVISIONED", it is necessary to specify `provisionedThroughput` for every Global Secondary Index (GSI) that exists in the table.
  */
  
  resources.models["Post"].modelDDBTable.globalSecondaryIndexes[0].provisionedThroughput = {
    readCapacityUnits: 5,
    writeCapacityUnits: 5
  }; 
}
```

### Example - Enable point-in-time recovery for DynamoDB table
Enable/disable [DynamoDB point-in-time recovery](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-dynamodb-table-pointintimerecoveryspecification.html) for each `@model` table.

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.models['Post'].modelDDBTable.pointInTimeRecoverySpecification = {
    pointInTimeRecoveryEnabled: true
  }
}
```

## Customize Amplify-generated resources for @searchable (OpenSearch) directive

Apply all the overrides in the `override(...)` function. For example, to modify the OpenSearch instance count:

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchDomain.elasticsearchClusterConfig = {
    ...resources.opensearch.OpenSearchDomain.elasticsearchClusterConfig,
    instanceCount: 6
  }
}
```

You can override the following @searchable directive resources that Amplify generates:

|Amplify-generated resource|Description|
|-|-|
[OpenSearchDataSource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html)|The AppSync data source representing the OpenSearch integration|
[OpenSearchAccessIAMRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|IAM role to access OpenSearch domain|
[OpenSearchAccessIAMRoleDefaultPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to access OpenSearch domain|
[OpenSearchDomain](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-elasticsearch-domain.html)|OpenSearch domain containing the @searchable data|
[OpenSearchStreamingLambdaIAMRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|IAM role to stream DynamoDB data to OpenSearch domain|
[OpenSearchStreamingLambdaIAMRoleDefaultPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to stream DynamoDB data to OpenSearch domain|
[CloudwatchLogsAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy for granting CloudWatch logs access|
[OpenSearchStreamingLambdaFunction](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)|Lambda function to stream DynamoDB data to OpenSearch domain|
[OpenSearchModelLambdaMapping](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-eventsourcemapping.html)|Event source mapping for DynamoDB table stream to Lambda function|

### Example - Configure Runtime for Streaming Lambda

You can define the runtime for the `@searchable` by setting the runtime value on the function object itself. This can be done to resolve a deprecated runtime in the event that you cannot upgrade your version of the Amplify CLI.

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchStreamingLambdaFunction.runtime = 'python3.9';
}
```

### Example - Configure OpenSearch Streaming function name
Override the name of the AWS Lambda searchable streaming function

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchStreamingLambdaFunction.FunctionName = 'CustomFunctionName';
}

```

### Example - Configure OpenSearch instance version

Override the `elasticsearchVersion` in the OpenSearch domain created by `@searchable`

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchDomain.elasticsearchVersion = 'OpenSearch_1.3';
}
```
### Example - Configure OpenSearch instance type

Override the type of instance launched into the OpenSearch domain created by `@searchable`

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchDomain.elasticsearchClusterConfig = {
    ...resources.opensearch.OpenSearchDomain.elasticsearchClusterConfig,
    instanceType: "m3.medium.elasticsearch",
  };
}
```
### Example - Configure OpenSearch instance count
Override the number of instances launched into the OpenSearch domain created by `@searchable`

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchDomain.elasticsearchClusterConfig = {
    ...resources.opensearch.OpenSearchDomain.elasticsearchClusterConfig,
    instanceCount : 2
  };
}
```

### Example - Configure OpenSearch EBS volume size
Override the amount of disk space allocated to each instance in the OpenSearch domain created by `@searchable`

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.opensearch.OpenSearchDomain.ebsOptions={
    ...resources.opensearch.OpenSearchDomain.ebsOptions,
    volumeSize:10
  }    
}
```

## Customize Amplify-generated resources for @predictions directive

Apply all the overrides in the `override(...)` function. For example, to add a Path to IAM role that facilitates text translation:

```ts
import { AmplifyApiGraphQlResourceStackTemplate } from '@aws-amplify/cli-extensibility-helper';

export function override(resources: AmplifyApiGraphQlResourceStackTemplate) {
  resources.predictions.TranslateDataSourceServiceRole.path = "/my/organization/"
}
```

You can override the following @predictions directive resources that Amplify generates:

|Amplify-generated resource|Description|
|-|-|
|[RekognitionDataSource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html)|AppSync HTTP data source to connect to Amazon Rekognition service|
|[RekognitionDataSourceServiceRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|AppSync service role to connect to Amazon Rekognition|
|[TranslateDataSource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html)|AppSync HTTP data source to connect to Amazon Translate service|
|[translateTextAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to connect to Amazon Translate|
|[LambdaDataSource](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-appsync-datasource.html)|AppSync Lambda data source to connect to Amazon Polly|
|[LambdaDataSourceServiceRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|AppSync service role to connect to Lambda function calling Amazon Polly|
|[LambdaDataSourceServiceRoleDefaultPolicy](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy for AppSync to connect to Lambda function calling Amazon Polly|
|[TranslateDataSourceServiceRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|AppSync service role to connect to Amazon Translate|
|[predictionsLambdaIAMRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|IAM role for Lambda function calling Amazon Polly|
|[predictionsLambdaFunction](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-lambda-function.html)|Lambda function calling Amazon Polly|
|[PredictionsLambdaAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy for Lambda function to access Amazon Polly|
|[predictionsIAMRole](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-role.html)|IAM role to access s3 bucket used by @predictions|
|[PredictionsStorageAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to access S3 bucket used by @predictions|
|[identifyTextAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to enable Identify Text|
|[identifyLabelsAccess](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-iam-policy.html)|IAM policy to enable Identify Text|

## Place AppSync Resolvers in Custom-named Stacks

If you have a particularly large GraphQL schema, you may run into issues with too many resources defined in a stack. The most common case where this happens is in the ConnectionStack which contains the resolvers for all of the relational directives in the schema.

Creating a stack mapping does not create an additional root stack for the Amplify environment. All mapped stacks will still be placed under the existing Amplify environment root stack.
To map a resolver to a different stack, update `<project root>/amplify/api/<api name>/transform.conf.json` with a "StackMapping" block. The StackMapping defines a map from resolver logical ID to stack name.

```json
{
  "Version": 5,
  "ElasticsearchWarning": true,
  "StackMapping": {
    "<Resolver logical ID>": "Custom stack name",
  }
}
```

The easiest way to determine a resolver logical ID is to run `amplify api gql-compile` and note the resolver logical ID in the list of Resources in the generated CloudFormation stack.
Resolvers for model operations will be of the form `<Get | List | Create | Update | Delete><model name>Resolver`. Resolvers for relational directives are of the form `<model name><field name>Resolver`.

### Example

Given the following schema:

```graphql
type Blog @model {
  id: ID!
  name: String!
  posts: [Post] @hasMany
}

type Post @model {
  id: ID!
  title: String!
  content: String
  blog: Blog @belongsTo
}
```

To map the CreatePostResolver and the relational resolvers to a stack named 'MyCustomStack', add the following in `transform.conf.json`:

```json
"StackMapping": {
  "CreatePostResolver": "MyCustomStack",
  "BlogpostsResolver": "MyCustomStack",
  "PostblogResolver": "MyCustomStack",
}
```
