Amplify has re-imagined the way frontend developers build fullstack applications. Develop and deploy without the hassle.

Page updated May 2, 2024

Overriding resources

By using overrides, you may create a backend that the Amplify libraries or client config is unable to interpret properly. Always test changes in a staging environment.

When defining resources, you can access some underlying AWS Cloud Development Kit (CDK) construct properties to modify resource configurations. This allows you to customize backend resources beyond what is offered through the define* functions.

Overrides are defined in the amplify/backend.ts file after the defineBackend call has been made.

amplify/backend.ts
1import { defineBackend } from '@aws-amplify/backend';
2import { auth } from './auth/resource';
3import { data } from './data/resource';
4
5const backend = defineBackend({
6 auth,
7 data
8});
9
10// overrides go here

The backend object exposes a resources property with objects for each of the components passed into the defineBackend function. Each of these resource objects exposes underlying L1 and L2 AWS CDK constructs that you can modify.

For example, here is how you can access the Cognito user pool that is created by defineAuth and set a custom removal policy on the resource.

amplify/backend.ts
1import { defineBackend } from '@aws-amplify/backend';
2import { auth } from './auth/resource';
3import { UserPool } from 'aws-cdk-lib/aws-cognito';
4import { RemovalPolicy } from 'aws-cdk-lib';
5
6const backend = defineBackend({
7 auth
8});
9
10const userPool = backend.auth.resources.userPool as UserPool;
11userPool.applyRemovalPolicy(RemovalPolicy.RETAIN_ON_UPDATE_OR_DELETE);

Most L1 and L2 AWS CDK constructs that are used by the define* functions are accessible in this way.

Example - Grant access permissions between resources

Consider the case that we want to grant a function created by defineFunction access to call the Cognito user pool created by defineAuth. This can be accomplished with the following overrides.

amplify/backend.ts
1import { defineBackend } from '@aws-amplify/backend';
2import { auth } from './auth/resource';
3import { data } from './data/resource';
4import { demoFunction } from './functions/demo-function/resource';
5import { UserPool } from 'aws-cdk-lib/aws-cognito';
6import { Function } from 'aws-cdk-lib/aws-lambda';
7
8const backend = defineBackend({
9 auth,
10 data,
11 demoFunction
12});
13
14const userPool = backend.auth.resources.userPool as UserPool;
15const lambdaFunction = backend.demoFunction.resources.lambda as Function;
16
17// grant the lambdaFunction read access to users
18userPool.grant(lambdaFunction, 'cognito:GetUser', 'cognito:ListUsers');
19
20// pass the Lambda the UserPool ID so that the Lambda can use it to make SDK calls
21lambdaFunction.addEnvironment('USER_POOL_ID', userPool.userPoolId);

Example - Mutate synthesized CloudFormation

It's possible to reach all the way down to the raw CloudFormation to mutate properties using addPropertyOverride on an AWS CDK construct. To edit the password policies of the Cognito user pool in defineAuth, you can use the following code.

amplify/backend.ts
1import { defineBackend } from '@aws-amplify/backend';
2import { auth } from './auth/resource';
3
4const backend = defineBackend({
5 auth
6});
7
8// override user pool password policies
9backend.auth.resources.cfnResources.cfnUserPool.addPropertyOverride(
10 'Policies',
11 {
12 PasswordPolicy: {
13 MinimumLength: 10,
14 RequireLowercase: true,
15 RequireNumbers: true,
16 RequireSymbols: true,
17 RequireUppercase: true,
18 TemporaryPasswordValidityDays: 20
19 }
20 }
21);

Note the usage of auth.resources.cfnResources. This property exposes L1 CDK constructs that map one-to-one with the underlying CloudFormation properties.

The auth.resources.cfnResources.cfnUserPool property in the above example directly maps to the AWS::Cognito::UserPool CloudFormation resource.

This is different from auth.resources.userPool in the first example, which is an L2 CDK construct. These are constructs that provide a convenient interface around several related L1 constructs.

Example - Add tags to resources

amplify/backend.ts
1import { defineBackend } from '@aws-amplify/backend';
2import { auth } from './auth/resource';
3import { data } from './data/resource';
4
5const backend = defineBackend({
6 auth,
7 data
8});
9
10backend.data.resources.cfnResources.cfnGraphqlApi.addPropertyOverride('Tags', [
11 {
12 Key: 'graphqlapi-tag-1',
13 Value: 'graphql-tag-value-1'
14 },
15 {
16 Key: 'graphqlapi-tag-2',
17 Value: 'graphql-tag-value-2'
18 }
19]);

For situations where you need even more customization of your app backend, see the documentation on custom resources.