Deploy AWS Amplify Applications

The aws:amplify/app:App resource, part of the Pulumi AWS provider, defines an Amplify app that connects a Git repository to AWS’s fullstack hosting platform. This guide focuses on four capabilities: repository connection and authentication, build pipeline configuration, automatic branch deployments, and URL routing and security headers.

Amplify apps connect to existing Git repositories and may reference IAM roles for service permissions. The examples are intentionally small. Combine them with your own repository URLs, authentication tokens, and IAM configuration.

Deploy a frontend app with build configuration

Most deployments start by connecting a repository and defining how to build and serve the application.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    repository: "https://github.com/example/app",
    buildSpec: `version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: build
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
`,
    customRules: [{
        source: "/<*>",
        status: "404",
        target: "/index.html",
    }],
    environmentVariables: {
        ENV: "test",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    repository="https://github.com/example/app",
    build_spec="""version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: build
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
""",
    custom_rules=[{
        "source": "/<*>",
        "status": "404",
        "target": "/index.html",
    }],
    environment_variables={
        "ENV": "test",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name:       pulumi.String("example"),
			Repository: pulumi.String("https://github.com/example/app"),
			BuildSpec: pulumi.String(`version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: build
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
`),
			CustomRules: amplify.AppCustomRuleArray{
				&amplify.AppCustomRuleArgs{
					Source: pulumi.String("/<*>"),
					Status: pulumi.String("404"),
					Target: pulumi.String("/index.html"),
				},
			},
			EnvironmentVariables: pulumi.StringMap{
				"ENV": pulumi.String("test"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        Repository = "https://github.com/example/app",
        BuildSpec = @"version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: build
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
",
        CustomRules = new[]
        {
            new Aws.Amplify.Inputs.AppCustomRuleArgs
            {
                Source = "/<*>",
                Status = "404",
                Target = "/index.html",
            },
        },
        EnvironmentVariables = 
        {
            { "ENV", "test" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import com.pulumi.aws.amplify.inputs.AppCustomRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .repository("https://github.com/example/app")
            .buildSpec("""
version: 0.1
frontend:
  phases:
    preBuild:
      commands:
        - yarn install
    build:
      commands:
        - yarn run build
  artifacts:
    baseDirectory: build
    files:
      - '**/*'
  cache:
    paths:
      - node_modules/**/*
            """)
            .customRules(AppCustomRuleArgs.builder()
                .source("/<*>")
                .status("404")
                .target("/index.html")
                .build())
            .environmentVariables(Map.of("ENV", "test"))
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      repository: https://github.com/example/app
      buildSpec: |
        version: 0.1
        frontend:
          phases:
            preBuild:
              commands:
                - yarn install
            build:
              commands:
                - yarn run build
          artifacts:
            baseDirectory: build
            files:
              - '**/*'
          cache:
            paths:
              - node_modules/**/*        
      customRules:
        - source: /<*>
          status: '404'
          target: /index.html
      environmentVariables:
        ENV: test

The repository property points to your Git URL. The buildSpec defines the build pipeline: dependency installation (preBuild), build commands, and output artifacts. The customRules array handles client-side routing by redirecting 404s to index.html. Environment variables pass configuration to the build process.

Authenticate with GitHub using access tokens

Private repositories require authentication so Amplify can create webhooks and deploy keys.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    repository: "https://github.com/example/app",
    accessToken: "...",
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    repository="https://github.com/example/app",
    access_token="...")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name:        pulumi.String("example"),
			Repository:  pulumi.String("https://github.com/example/app"),
			AccessToken: pulumi.String("..."),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        Repository = "https://github.com/example/app",
        AccessToken = "...",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .repository("https://github.com/example/app")
            .accessToken("...")
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      repository: https://github.com/example/app
      accessToken: '...'

The accessToken property accepts a GitHub personal access token with repository write permissions. Amplify uses this token once during setup to create webhooks and deploy keys, then discards it. After initial deployment, you can remove the token from your configuration. Store tokens in a secrets manager rather than hardcoding them.

Enable automatic branch deployments

Teams working with feature branches often want preview environments created automatically when new branches are pushed.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    enableAutoBranchCreation: true,
    autoBranchCreationPatterns: [
        "*",
        "*/**",
    ],
    autoBranchCreationConfig: {
        enableAutoBuild: true,
    },
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    enable_auto_branch_creation=True,
    auto_branch_creation_patterns=[
        "*",
        "*/**",
    ],
    auto_branch_creation_config={
        "enable_auto_build": True,
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name:                     pulumi.String("example"),
			EnableAutoBranchCreation: pulumi.Bool(true),
			AutoBranchCreationPatterns: pulumi.StringArray{
				pulumi.String("*"),
				pulumi.String("*/**"),
			},
			AutoBranchCreationConfig: &amplify.AppAutoBranchCreationConfigArgs{
				EnableAutoBuild: pulumi.Bool(true),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        EnableAutoBranchCreation = true,
        AutoBranchCreationPatterns = new[]
        {
            "*",
            "*/**",
        },
        AutoBranchCreationConfig = new Aws.Amplify.Inputs.AppAutoBranchCreationConfigArgs
        {
            EnableAutoBuild = true,
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import com.pulumi.aws.amplify.inputs.AppAutoBranchCreationConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .enableAutoBranchCreation(true)
            .autoBranchCreationPatterns(            
                "*",
                "*/**")
            .autoBranchCreationConfig(AppAutoBranchCreationConfigArgs.builder()
                .enableAutoBuild(true)
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      enableAutoBranchCreation: true # The default patterns added by the Amplify Console.
      autoBranchCreationPatterns:
        - '*'
        - '*/**'
      autoBranchCreationConfig:
        enableAutoBuild: true

The enableAutoBranchCreation property activates automatic deployments. The autoBranchCreationPatterns array defines which branch names trigger deployments (wildcards match all branches). The autoBranchCreationConfig block controls whether new branches build automatically.

Protect preview environments with basic auth

Preview deployments often need password protection before features are production-ready.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
import * as std from "@pulumi/std";

const example = new aws.amplify.App("example", {
    name: "example",
    enableBasicAuth: true,
    basicAuthCredentials: std.base64encode({
        input: "username1:password1",
    }).then(invoke => invoke.result),
});
import pulumi
import pulumi_aws as aws
import pulumi_std as std

example = aws.amplify.App("example",
    name="example",
    enable_basic_auth=True,
    basic_auth_credentials=std.base64encode(input="username1:password1").result)
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi-std/sdk/go/std"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		invokeBase64encode, err := std.Base64encode(ctx, &std.Base64encodeArgs{
			Input: "username1:password1",
		}, nil)
		if err != nil {
			return err
		}
		_, err = amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name:                 pulumi.String("example"),
			EnableBasicAuth:      pulumi.Bool(true),
			BasicAuthCredentials: pulumi.String(invokeBase64encode.Result),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;
using Std = Pulumi.Std;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        EnableBasicAuth = true,
        BasicAuthCredentials = Std.Base64encode.Invoke(new()
        {
            Input = "username1:password1",
        }).Apply(invoke => invoke.Result),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import com.pulumi.std.StdFunctions;
import com.pulumi.std.inputs.Base64encodeArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .enableBasicAuth(true)
            .basicAuthCredentials(StdFunctions.base64encode(Base64encodeArgs.builder()
                .input("username1:password1")
                .build()).result())
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      enableBasicAuth: true
      basicAuthCredentials:
        fn::invoke:
          function: std:base64encode
          arguments:
            input: username1:password1
          return: result

The enableBasicAuth property activates HTTP basic authentication across all branches. The basicAuthCredentials property accepts a base64-encoded “username:password” string. Use a secrets manager to generate and store credentials securely.

Configure URL routing and redirects

Single-page applications need URL rewriting to route all paths to index.html, while API proxying requires redirects to backend services.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    customRules: [
        {
            source: "/api/<*>",
            status: "200",
            target: "https://api.example.com/api/<*>",
        },
        {
            source: "</^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>",
            status: "200",
            target: "/index.html",
        },
    ],
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    custom_rules=[
        {
            "source": "/api/<*>",
            "status": "200",
            "target": "https://api.example.com/api/<*>",
        },
        {
            "source": "</^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>",
            "status": "200",
            "target": "/index.html",
        },
    ])
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name: pulumi.String("example"),
			CustomRules: amplify.AppCustomRuleArray{
				&amplify.AppCustomRuleArgs{
					Source: pulumi.String("/api/<*>"),
					Status: pulumi.String("200"),
					Target: pulumi.String("https://api.example.com/api/<*>"),
				},
				&amplify.AppCustomRuleArgs{
					Source: pulumi.String("</^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>"),
					Status: pulumi.String("200"),
					Target: pulumi.String("/index.html"),
				},
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        CustomRules = new[]
        {
            new Aws.Amplify.Inputs.AppCustomRuleArgs
            {
                Source = "/api/<*>",
                Status = "200",
                Target = "https://api.example.com/api/<*>",
            },
            new Aws.Amplify.Inputs.AppCustomRuleArgs
            {
                Source = "</^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>",
                Status = "200",
                Target = "/index.html",
            },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import com.pulumi.aws.amplify.inputs.AppCustomRuleArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .customRules(            
                AppCustomRuleArgs.builder()
                    .source("/api/<*>")
                    .status("200")
                    .target("https://api.example.com/api/<*>")
                    .build(),
                AppCustomRuleArgs.builder()
                    .source("</^[^.]+$|\\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>")
                    .status("200")
                    .target("/index.html")
                    .build())
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      customRules:
        - source: /api/<*>
          status: '200'
          target: https://api.example.com/api/<*>
        - source: </^[^.]+$|\.(?!(css|gif|ico|jpg|js|png|txt|svg|woff|ttf|map|json)$)([^.]+$)/>
          status: '200'
          target: /index.html

The customRules array defines routing behavior. Each rule specifies a source pattern, HTTP status code, and target URL. The first rule proxies API requests to an external service. The second rule handles SPA routing by serving index.html for all non-asset paths.

Specify a custom build container image

Applications with specific runtime requirements can override the default Amplify build image.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    environmentVariables: {
        _CUSTOM_IMAGE: "node:16",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    environment_variables={
        "_CUSTOM_IMAGE": "node:16",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name: pulumi.String("example"),
			EnvironmentVariables: pulumi.StringMap{
				"_CUSTOM_IMAGE": pulumi.String("node:16"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        EnvironmentVariables = 
        {
            { "_CUSTOM_IMAGE", "node:16" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .environmentVariables(Map.of("_CUSTOM_IMAGE", "node:16"))
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      environmentVariables:
        _CUSTOM_IMAGE: node:16

The _CUSTOM_IMAGE environment variable tells Amplify which Docker image to use for builds. This example specifies Node.js 16. You can reference any public Docker image or images from your own ECR repositories.

Add security headers to all responses

Production applications typically require security headers to protect against common web vulnerabilities.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    customHeaders: `customHeaders:
  - pattern: '**'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: \\"default-src 'self'\\"
`,
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    custom_headers="""customHeaders:
  - pattern: '**'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: \"default-src 'self'\"
""")
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name: pulumi.String("example"),
			CustomHeaders: pulumi.String(`customHeaders:
  - pattern: '**'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: \"default-src 'self'\"
`),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        CustomHeaders = @"customHeaders:
  - pattern: '**'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: \""default-src 'self'\""
",
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .customHeaders("""
customHeaders:
  - pattern: '**'
    headers:
      - key: 'Strict-Transport-Security'
        value: 'max-age=31536000; includeSubDomains'
      - key: 'X-Frame-Options'
        value: 'SAMEORIGIN'
      - key: 'X-XSS-Protection'
        value: '1; mode=block'
      - key: 'X-Content-Type-Options'
        value: 'nosniff'
      - key: 'Content-Security-Policy'
        value: \"default-src 'self'\"
            """)
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      customHeaders: |
        customHeaders:
          - pattern: '**'
            headers:
              - key: 'Strict-Transport-Security'
                value: 'max-age=31536000; includeSubDomains'
              - key: 'X-Frame-Options'
                value: 'SAMEORIGIN'
              - key: 'X-XSS-Protection'
                value: '1; mode=block'
              - key: 'X-Content-Type-Options'
                value: 'nosniff'
              - key: 'Content-Security-Policy'
                value: \"default-src 'self'\"        

The customHeaders property accepts YAML-formatted header configuration. Each pattern defines which routes receive the headers. This example applies security headers globally, including Strict-Transport-Security for HTTPS enforcement and Content-Security-Policy to prevent XSS attacks.

Increase build instance compute capacity

Large applications with long build times or memory-intensive compilation can benefit from larger build instances.

import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";

const example = new aws.amplify.App("example", {
    name: "example",
    jobConfig: {
        buildComputeType: "STANDARD_8GB",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.amplify.App("example",
    name="example",
    job_config={
        "build_compute_type": "STANDARD_8GB",
    })
package main

import (
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amplify"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amplify.NewApp(ctx, "example", &amplify.AppArgs{
			Name: pulumi.String("example"),
			JobConfig: &amplify.AppJobConfigArgs{
				BuildComputeType: pulumi.String("STANDARD_8GB"),
			},
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var example = new Aws.Amplify.App("example", new()
    {
        Name = "example",
        JobConfig = new Aws.Amplify.Inputs.AppJobConfigArgs
        {
            BuildComputeType = "STANDARD_8GB",
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amplify.App;
import com.pulumi.aws.amplify.AppArgs;
import com.pulumi.aws.amplify.inputs.AppJobConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;

public class App {
    public static void main(String[] args) {
        Pulumi.run(App::stack);
    }

    public static void stack(Context ctx) {
        var example = new App("example", AppArgs.builder()
            .name("example")
            .jobConfig(AppJobConfigArgs.builder()
                .buildComputeType("STANDARD_8GB")
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:amplify:App
    properties:
      name: example
      jobConfig:
        buildComputeType: STANDARD_8GB

The jobConfig property controls build instance size. The buildComputeType property accepts values like STANDARD_8GB for increased memory and CPU. Larger instances reduce build times but increase costs.

Beyond these examples

These snippets focus on specific app-level features: repository connection and build configuration, authentication and access control, routing, redirects, and security headers, and build environment customization. They’re intentionally minimal rather than full hosting configurations.

The examples may reference pre-existing infrastructure such as Git repositories, IAM service roles for Amplify, and personal access tokens or OAuth tokens. They focus on configuring the app rather than provisioning everything around it.

To keep things focused, common Amplify patterns are omitted, including:

  • Branch-specific configuration (use aws.amplify.Branch resource)
  • Domain and SSL certificate management (use aws.amplify.DomainAssociation)
  • Backend environment integration (use platform: WEB_COMPUTE)
  • Cache configuration (cacheConfig property)

These omissions are intentional: the goal is to illustrate how each app feature is wired, not provide drop-in hosting modules. See the Amplify App resource reference for all available configuration options.

Let's deploy AWS Amplify Applications

Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.

Try Pulumi Cloud for FREE

Frequently Asked Questions

Authentication & Repository Setup
Why am I getting a BadRequestException about tokens when creating my app?
When creating an Amplify app with a repository, you must provide either accessToken (for GitHub) or oauthToken (for other Git providers) for authentication. Without a valid token, you’ll receive “BadRequestException: You should at least provide one valid token.”
How do I authenticate my Amplify app with a GitHub repository?
Create a GitHub personal access token with write access to your repository, then set it as the accessToken property. This token creates a webhook and read-only deploy key for your app.
What happens to my access token after deployment?
Access tokens are not stored by AWS after initial setup. Once you’ve successfully deployed your app, you can remove the accessToken or oauthToken from your configuration and delete the token.
Do I need an access token when importing an existing Amplify app?
No, you can omit accessToken if you’re importing an app that was created via the Amplify Console using OAuth authentication.
Branch Management
How do I enable automatic branch creation for my app?
Set enableAutoBranchCreation to true, define glob patterns in autoBranchCreationPatterns (e.g., ["*", "*/**"]), and configure build settings in autoBranchCreationConfig.
What's the difference between enableBranchAutoBuild and enableAutoBranchCreation?
enableBranchAutoBuild controls whether existing branches automatically build when code is pushed. enableAutoBranchCreation creates new branches in Amplify when matching branches are created in your repository.
How do I automatically remove branches when I delete them from Git?
Set enableBranchAutoDeletion to true to automatically disconnect branches in Amplify Console when you delete them from your Git repository.
Security & Access Control
How do I set up basic authentication for my Amplify app?
Enable enableBasicAuth and provide base64-encoded credentials in basicAuthCredentials using the format “username:password”. This applies to all branches in the app.
How do I add custom security headers to my app?
Configure customHeaders in YAML format with patterns and header key-value pairs. Common headers include Strict-Transport-Security, X-Frame-Options, and Content-Security-Policy.
Build Configuration
How do I use a custom Docker image for my builds?
Set the _CUSTOM_IMAGE environment variable to your desired image (e.g., “node:16”). This special environment variable tells Amplify which Docker image to use.
How do I change the build instance compute type?
Configure jobConfig with buildComputeType set to your desired compute size (e.g., “STANDARD_8GB”).
What's the difference between WEB and WEB_COMPUTE platforms?
The platform property accepts WEB (default) or WEB_COMPUTE. WEB is for static sites, while WEB_COMPUTE enables server-side rendering capabilities.
Routing & Redirects
How do I configure redirects and rewrites for my app?
Use customRules with source, target, and status fields. You can use regex patterns for advanced routing, such as SPA fallback rules or API proxying.

Using a different cloud?

Explore serverless guides for other cloud providers: