The aws:apprunner/service:Service resource, part of the Pulumi AWS provider, defines an App Runner service that deploys and runs containerized web applications from source code or container images. This guide focuses on three capabilities: GitHub repository deployment with build configuration, pre-built container image deployment, and X-Ray tracing integration.
App Runner services require either a GitHub connection (for code repositories) or container images in ECR. VPC egress requires a VPC connector; observability requires an ObservabilityConfiguration resource. The examples are intentionally small. Combine them with your own health checks, instance configuration, and auto scaling policies.
Deploy from a GitHub repository with build configuration
Teams building containerized applications from source often connect App Runner to a GitHub repository. App Runner clones the code, runs your build command, and deploys the resulting container.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.apprunner.Service("example", {
serviceName: "example",
sourceConfiguration: {
authenticationConfiguration: {
connectionArn: exampleAwsApprunnerConnection.arn,
},
codeRepository: {
codeConfiguration: {
codeConfigurationValues: {
buildCommand: "python setup.py develop",
port: "8000",
runtime: "PYTHON_3",
startCommand: "python runapp.py",
},
configurationSource: "API",
},
repositoryUrl: "https://github.com/example/my-example-python-app",
sourceCodeVersion: {
type: "BRANCH",
value: "main",
},
},
},
networkConfiguration: {
egressConfiguration: {
egressType: "VPC",
vpcConnectorArn: connector.arn,
},
},
tags: {
Name: "example-apprunner-service",
},
});
import pulumi
import pulumi_aws as aws
example = aws.apprunner.Service("example",
service_name="example",
source_configuration={
"authentication_configuration": {
"connection_arn": example_aws_apprunner_connection["arn"],
},
"code_repository": {
"code_configuration": {
"code_configuration_values": {
"build_command": "python setup.py develop",
"port": "8000",
"runtime": "PYTHON_3",
"start_command": "python runapp.py",
},
"configuration_source": "API",
},
"repository_url": "https://github.com/example/my-example-python-app",
"source_code_version": {
"type": "BRANCH",
"value": "main",
},
},
},
network_configuration={
"egress_configuration": {
"egress_type": "VPC",
"vpc_connector_arn": connector["arn"],
},
},
tags={
"Name": "example-apprunner-service",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apprunner"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := apprunner.NewService(ctx, "example", &apprunner.ServiceArgs{
ServiceName: pulumi.String("example"),
SourceConfiguration: &apprunner.ServiceSourceConfigurationArgs{
AuthenticationConfiguration: &apprunner.ServiceSourceConfigurationAuthenticationConfigurationArgs{
ConnectionArn: pulumi.Any(exampleAwsApprunnerConnection.Arn),
},
CodeRepository: &apprunner.ServiceSourceConfigurationCodeRepositoryArgs{
CodeConfiguration: &apprunner.ServiceSourceConfigurationCodeRepositoryCodeConfigurationArgs{
CodeConfigurationValues: &apprunner.ServiceSourceConfigurationCodeRepositoryCodeConfigurationCodeConfigurationValuesArgs{
BuildCommand: pulumi.String("python setup.py develop"),
Port: pulumi.String("8000"),
Runtime: pulumi.String("PYTHON_3"),
StartCommand: pulumi.String("python runapp.py"),
},
ConfigurationSource: pulumi.String("API"),
},
RepositoryUrl: pulumi.String("https://github.com/example/my-example-python-app"),
SourceCodeVersion: &apprunner.ServiceSourceConfigurationCodeRepositorySourceCodeVersionArgs{
Type: pulumi.String("BRANCH"),
Value: pulumi.String("main"),
},
},
},
NetworkConfiguration: &apprunner.ServiceNetworkConfigurationArgs{
EgressConfiguration: &apprunner.ServiceNetworkConfigurationEgressConfigurationArgs{
EgressType: pulumi.String("VPC"),
VpcConnectorArn: pulumi.Any(connector.Arn),
},
},
Tags: pulumi.StringMap{
"Name": pulumi.String("example-apprunner-service"),
},
})
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.AppRunner.Service("example", new()
{
ServiceName = "example",
SourceConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationArgs
{
AuthenticationConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationAuthenticationConfigurationArgs
{
ConnectionArn = exampleAwsApprunnerConnection.Arn,
},
CodeRepository = new Aws.AppRunner.Inputs.ServiceSourceConfigurationCodeRepositoryArgs
{
CodeConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationCodeRepositoryCodeConfigurationArgs
{
CodeConfigurationValues = new Aws.AppRunner.Inputs.ServiceSourceConfigurationCodeRepositoryCodeConfigurationCodeConfigurationValuesArgs
{
BuildCommand = "python setup.py develop",
Port = "8000",
Runtime = "PYTHON_3",
StartCommand = "python runapp.py",
},
ConfigurationSource = "API",
},
RepositoryUrl = "https://github.com/example/my-example-python-app",
SourceCodeVersion = new Aws.AppRunner.Inputs.ServiceSourceConfigurationCodeRepositorySourceCodeVersionArgs
{
Type = "BRANCH",
Value = "main",
},
},
},
NetworkConfiguration = new Aws.AppRunner.Inputs.ServiceNetworkConfigurationArgs
{
EgressConfiguration = new Aws.AppRunner.Inputs.ServiceNetworkConfigurationEgressConfigurationArgs
{
EgressType = "VPC",
VpcConnectorArn = connector.Arn,
},
},
Tags =
{
{ "Name", "example-apprunner-service" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apprunner.Service;
import com.pulumi.aws.apprunner.ServiceArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationAuthenticationConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationCodeRepositoryArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationCodeRepositoryCodeConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationCodeRepositoryCodeConfigurationCodeConfigurationValuesArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationCodeRepositorySourceCodeVersionArgs;
import com.pulumi.aws.apprunner.inputs.ServiceNetworkConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceNetworkConfigurationEgressConfigurationArgs;
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 Service("example", ServiceArgs.builder()
.serviceName("example")
.sourceConfiguration(ServiceSourceConfigurationArgs.builder()
.authenticationConfiguration(ServiceSourceConfigurationAuthenticationConfigurationArgs.builder()
.connectionArn(exampleAwsApprunnerConnection.arn())
.build())
.codeRepository(ServiceSourceConfigurationCodeRepositoryArgs.builder()
.codeConfiguration(ServiceSourceConfigurationCodeRepositoryCodeConfigurationArgs.builder()
.codeConfigurationValues(ServiceSourceConfigurationCodeRepositoryCodeConfigurationCodeConfigurationValuesArgs.builder()
.buildCommand("python setup.py develop")
.port("8000")
.runtime("PYTHON_3")
.startCommand("python runapp.py")
.build())
.configurationSource("API")
.build())
.repositoryUrl("https://github.com/example/my-example-python-app")
.sourceCodeVersion(ServiceSourceConfigurationCodeRepositorySourceCodeVersionArgs.builder()
.type("BRANCH")
.value("main")
.build())
.build())
.build())
.networkConfiguration(ServiceNetworkConfigurationArgs.builder()
.egressConfiguration(ServiceNetworkConfigurationEgressConfigurationArgs.builder()
.egressType("VPC")
.vpcConnectorArn(connector.arn())
.build())
.build())
.tags(Map.of("Name", "example-apprunner-service"))
.build());
}
}
resources:
example:
type: aws:apprunner:Service
properties:
serviceName: example
sourceConfiguration:
authenticationConfiguration:
connectionArn: ${exampleAwsApprunnerConnection.arn}
codeRepository:
codeConfiguration:
codeConfigurationValues:
buildCommand: python setup.py develop
port: '8000'
runtime: PYTHON_3
startCommand: python runapp.py
configurationSource: API
repositoryUrl: https://github.com/example/my-example-python-app
sourceCodeVersion:
type: BRANCH
value: main
networkConfiguration:
egressConfiguration:
egressType: VPC
vpcConnectorArn: ${connector.arn}
tags:
Name: example-apprunner-service
The codeRepository block specifies the repository URL and branch to track. The codeConfigurationValues define how App Runner builds and runs your application: buildCommand installs dependencies, startCommand launches the server, runtime selects the language environment, and port exposes the HTTP endpoint. The authenticationConfiguration references a GitHub connection that grants App Runner access to private repositories. The networkConfiguration routes outbound traffic through a VPC connector, enabling access to RDS or internal services.
Deploy from a pre-built container image
Applications with existing container images can skip the build step by pointing App Runner at an ECR or public registry.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const example = new aws.apprunner.Service("example", {
serviceName: "example",
sourceConfiguration: {
imageRepository: {
imageConfiguration: {
port: "8000",
},
imageIdentifier: "public.ecr.aws/aws-containers/hello-app-runner:latest",
imageRepositoryType: "ECR_PUBLIC",
},
autoDeploymentsEnabled: false,
},
tags: {
Name: "example-apprunner-service",
},
});
import pulumi
import pulumi_aws as aws
example = aws.apprunner.Service("example",
service_name="example",
source_configuration={
"image_repository": {
"image_configuration": {
"port": "8000",
},
"image_identifier": "public.ecr.aws/aws-containers/hello-app-runner:latest",
"image_repository_type": "ECR_PUBLIC",
},
"auto_deployments_enabled": False,
},
tags={
"Name": "example-apprunner-service",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apprunner"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
_, err := apprunner.NewService(ctx, "example", &apprunner.ServiceArgs{
ServiceName: pulumi.String("example"),
SourceConfiguration: &apprunner.ServiceSourceConfigurationArgs{
ImageRepository: &apprunner.ServiceSourceConfigurationImageRepositoryArgs{
ImageConfiguration: &apprunner.ServiceSourceConfigurationImageRepositoryImageConfigurationArgs{
Port: pulumi.String("8000"),
},
ImageIdentifier: pulumi.String("public.ecr.aws/aws-containers/hello-app-runner:latest"),
ImageRepositoryType: pulumi.String("ECR_PUBLIC"),
},
AutoDeploymentsEnabled: pulumi.Bool(false),
},
Tags: pulumi.StringMap{
"Name": pulumi.String("example-apprunner-service"),
},
})
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.AppRunner.Service("example", new()
{
ServiceName = "example",
SourceConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationArgs
{
ImageRepository = new Aws.AppRunner.Inputs.ServiceSourceConfigurationImageRepositoryArgs
{
ImageConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationImageRepositoryImageConfigurationArgs
{
Port = "8000",
},
ImageIdentifier = "public.ecr.aws/aws-containers/hello-app-runner:latest",
ImageRepositoryType = "ECR_PUBLIC",
},
AutoDeploymentsEnabled = false,
},
Tags =
{
{ "Name", "example-apprunner-service" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apprunner.Service;
import com.pulumi.aws.apprunner.ServiceArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationImageRepositoryArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationImageRepositoryImageConfigurationArgs;
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 Service("example", ServiceArgs.builder()
.serviceName("example")
.sourceConfiguration(ServiceSourceConfigurationArgs.builder()
.imageRepository(ServiceSourceConfigurationImageRepositoryArgs.builder()
.imageConfiguration(ServiceSourceConfigurationImageRepositoryImageConfigurationArgs.builder()
.port("8000")
.build())
.imageIdentifier("public.ecr.aws/aws-containers/hello-app-runner:latest")
.imageRepositoryType("ECR_PUBLIC")
.build())
.autoDeploymentsEnabled(false)
.build())
.tags(Map.of("Name", "example-apprunner-service"))
.build());
}
}
resources:
example:
type: aws:apprunner:Service
properties:
serviceName: example
sourceConfiguration:
imageRepository:
imageConfiguration:
port: '8000'
imageIdentifier: public.ecr.aws/aws-containers/hello-app-runner:latest
imageRepositoryType: ECR_PUBLIC
autoDeploymentsEnabled: false
tags:
Name: example-apprunner-service
The imageRepository block replaces codeRepository when deploying pre-built containers. The imageIdentifier points to your container image (ECR Public shown here; private ECR and Docker Hub are also supported). The imageRepositoryType tells App Runner which registry authentication to use. Setting autoDeploymentsEnabled to false prevents automatic redeployment when the image tag updates; set it to true for continuous deployment.
Enable X-Ray tracing for request monitoring
Production services often need distributed tracing to diagnose latency and errors across service boundaries.
import * as pulumi from "@pulumi/pulumi";
import * as aws from "@pulumi/aws";
const exampleObservabilityConfiguration = new aws.apprunner.ObservabilityConfiguration("example", {
observabilityConfigurationName: "example",
traceConfiguration: {
vendor: "AWSXRAY",
},
});
const example = new aws.apprunner.Service("example", {
serviceName: "example",
observabilityConfiguration: {
observabilityConfigurationArn: exampleObservabilityConfiguration.arn,
observabilityEnabled: true,
},
sourceConfiguration: {
imageRepository: {
imageConfiguration: {
port: "8000",
},
imageIdentifier: "public.ecr.aws/aws-containers/hello-app-runner:latest",
imageRepositoryType: "ECR_PUBLIC",
},
autoDeploymentsEnabled: false,
},
tags: {
Name: "example-apprunner-service",
},
});
import pulumi
import pulumi_aws as aws
example_observability_configuration = aws.apprunner.ObservabilityConfiguration("example",
observability_configuration_name="example",
trace_configuration={
"vendor": "AWSXRAY",
})
example = aws.apprunner.Service("example",
service_name="example",
observability_configuration={
"observability_configuration_arn": example_observability_configuration.arn,
"observability_enabled": True,
},
source_configuration={
"image_repository": {
"image_configuration": {
"port": "8000",
},
"image_identifier": "public.ecr.aws/aws-containers/hello-app-runner:latest",
"image_repository_type": "ECR_PUBLIC",
},
"auto_deployments_enabled": False,
},
tags={
"Name": "example-apprunner-service",
})
package main
import (
"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/apprunner"
"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)
func main() {
pulumi.Run(func(ctx *pulumi.Context) error {
exampleObservabilityConfiguration, err := apprunner.NewObservabilityConfiguration(ctx, "example", &apprunner.ObservabilityConfigurationArgs{
ObservabilityConfigurationName: pulumi.String("example"),
TraceConfiguration: &apprunner.ObservabilityConfigurationTraceConfigurationArgs{
Vendor: pulumi.String("AWSXRAY"),
},
})
if err != nil {
return err
}
_, err = apprunner.NewService(ctx, "example", &apprunner.ServiceArgs{
ServiceName: pulumi.String("example"),
ObservabilityConfiguration: &apprunner.ServiceObservabilityConfigurationArgs{
ObservabilityConfigurationArn: exampleObservabilityConfiguration.Arn,
ObservabilityEnabled: pulumi.Bool(true),
},
SourceConfiguration: &apprunner.ServiceSourceConfigurationArgs{
ImageRepository: &apprunner.ServiceSourceConfigurationImageRepositoryArgs{
ImageConfiguration: &apprunner.ServiceSourceConfigurationImageRepositoryImageConfigurationArgs{
Port: pulumi.String("8000"),
},
ImageIdentifier: pulumi.String("public.ecr.aws/aws-containers/hello-app-runner:latest"),
ImageRepositoryType: pulumi.String("ECR_PUBLIC"),
},
AutoDeploymentsEnabled: pulumi.Bool(false),
},
Tags: pulumi.StringMap{
"Name": pulumi.String("example-apprunner-service"),
},
})
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 exampleObservabilityConfiguration = new Aws.AppRunner.ObservabilityConfiguration("example", new()
{
ObservabilityConfigurationName = "example",
TraceConfiguration = new Aws.AppRunner.Inputs.ObservabilityConfigurationTraceConfigurationArgs
{
Vendor = "AWSXRAY",
},
});
var example = new Aws.AppRunner.Service("example", new()
{
ServiceName = "example",
ObservabilityConfiguration = new Aws.AppRunner.Inputs.ServiceObservabilityConfigurationArgs
{
ObservabilityConfigurationArn = exampleObservabilityConfiguration.Arn,
ObservabilityEnabled = true,
},
SourceConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationArgs
{
ImageRepository = new Aws.AppRunner.Inputs.ServiceSourceConfigurationImageRepositoryArgs
{
ImageConfiguration = new Aws.AppRunner.Inputs.ServiceSourceConfigurationImageRepositoryImageConfigurationArgs
{
Port = "8000",
},
ImageIdentifier = "public.ecr.aws/aws-containers/hello-app-runner:latest",
ImageRepositoryType = "ECR_PUBLIC",
},
AutoDeploymentsEnabled = false,
},
Tags =
{
{ "Name", "example-apprunner-service" },
},
});
});
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.apprunner.ObservabilityConfiguration;
import com.pulumi.aws.apprunner.ObservabilityConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ObservabilityConfigurationTraceConfigurationArgs;
import com.pulumi.aws.apprunner.Service;
import com.pulumi.aws.apprunner.ServiceArgs;
import com.pulumi.aws.apprunner.inputs.ServiceObservabilityConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationImageRepositoryArgs;
import com.pulumi.aws.apprunner.inputs.ServiceSourceConfigurationImageRepositoryImageConfigurationArgs;
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 exampleObservabilityConfiguration = new ObservabilityConfiguration("exampleObservabilityConfiguration", ObservabilityConfigurationArgs.builder()
.observabilityConfigurationName("example")
.traceConfiguration(ObservabilityConfigurationTraceConfigurationArgs.builder()
.vendor("AWSXRAY")
.build())
.build());
var example = new Service("example", ServiceArgs.builder()
.serviceName("example")
.observabilityConfiguration(ServiceObservabilityConfigurationArgs.builder()
.observabilityConfigurationArn(exampleObservabilityConfiguration.arn())
.observabilityEnabled(true)
.build())
.sourceConfiguration(ServiceSourceConfigurationArgs.builder()
.imageRepository(ServiceSourceConfigurationImageRepositoryArgs.builder()
.imageConfiguration(ServiceSourceConfigurationImageRepositoryImageConfigurationArgs.builder()
.port("8000")
.build())
.imageIdentifier("public.ecr.aws/aws-containers/hello-app-runner:latest")
.imageRepositoryType("ECR_PUBLIC")
.build())
.autoDeploymentsEnabled(false)
.build())
.tags(Map.of("Name", "example-apprunner-service"))
.build());
}
}
resources:
example:
type: aws:apprunner:Service
properties:
serviceName: example
observabilityConfiguration:
observabilityConfigurationArn: ${exampleObservabilityConfiguration.arn}
observabilityEnabled: true
sourceConfiguration:
imageRepository:
imageConfiguration:
port: '8000'
imageIdentifier: public.ecr.aws/aws-containers/hello-app-runner:latest
imageRepositoryType: ECR_PUBLIC
autoDeploymentsEnabled: false
tags:
Name: example-apprunner-service
exampleObservabilityConfiguration:
type: aws:apprunner:ObservabilityConfiguration
name: example
properties:
observabilityConfigurationName: example
traceConfiguration:
vendor: AWSXRAY
The observabilityConfiguration block enables AWS X-Ray tracing by referencing an ObservabilityConfiguration resource. The traceConfiguration vendor must be set to “AWSXRAY”. Once enabled, App Runner automatically instruments incoming requests and propagates trace context to downstream services, allowing you to visualize request flows in the X-Ray console.
Beyond these examples
These snippets focus on specific App Runner service features: code and image repository sources, VPC egress configuration, and X-Ray distributed tracing. They’re intentionally minimal rather than full application deployments.
The examples may reference pre-existing infrastructure such as GitHub connections (for code repositories), VPC connectors (for private egress), and ECR repositories or public container images. They focus on configuring the service rather than provisioning everything around it.
To keep things focused, common service patterns are omitted, including:
- Health check customization (healthCheckConfiguration)
- Instance sizing and IAM roles (instanceConfiguration)
- Auto scaling limits (autoScalingConfigurationArn)
- Custom encryption keys (encryptionConfiguration)
These omissions are intentional: the goal is to illustrate how each App Runner feature is wired, not provide drop-in production modules. See the App Runner Service resource reference for all available configuration options.
Let's deploy AWS App Runner Services
Get started with Pulumi Cloud, then follow our quick setup guide to deploy this infrastructure.
Try Pulumi Cloud for FREEFrequently Asked Questions
Deployment Sources & Configuration
buildCommand, startCommand, runtime), while image repositories use pre-built container images.authenticationConfiguration with a connectionArn. Public ECR images (ECR_PUBLIC) don’t require authentication, as shown in the image repository example.false to require manual deployments.Configuration & Immutability
serviceName and encryptionConfiguration are immutable. Changing these requires replacing the service.autoScalingConfigurationArn is required but App Runner uses the latest default auto-scaling configuration if you don’t provide one.Networking & Access
networkConfiguration.egressConfiguration with egressType: "VPC" and a vpcConnectorArn, as shown in the code repository example.serviceUrl subdomain that you can use to access your web application.Monitoring & Observability
aws.apprunner.ObservabilityConfiguration resource, then reference its ARN in your service’s observabilityConfiguration with observabilityEnabled: true.