Create AWS Managed Service for Prometheus Workspaces

The aws:amp/workspace:Workspace resource, part of the Pulumi AWS provider, provisions an Amazon Managed Service for Prometheus workspace: the container for storing and querying Prometheus metrics. This guide focuses on three capabilities: workspace creation with aliases and tags, CloudWatch logging integration, and customer-managed encryption.

AMP workspaces are standalone resources that can reference CloudWatch log groups for operational logging and KMS keys for encryption. The examples are intentionally small. Combine them with your own Prometheus remote write configuration and alert manager setup.

Create a workspace with an alias and tags

Most deployments start by creating a workspace with a human-readable alias and tags for organization.

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

const example = new aws.amp.Workspace("example", {
    alias: "example",
    tags: {
        Environment: "production",
    },
});
import pulumi
import pulumi_aws as aws

example = aws.amp.Workspace("example",
    alias="example",
    tags={
        "Environment": "production",
    })
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		_, err := amp.NewWorkspace(ctx, "example", &amp.WorkspaceArgs{
			Alias: pulumi.String("example"),
			Tags: pulumi.StringMap{
				"Environment": pulumi.String("production"),
			},
		})
		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.Amp.Workspace("example", new()
    {
        Alias = "example",
        Tags = 
        {
            { "Environment", "production" },
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.amp.Workspace;
import com.pulumi.aws.amp.WorkspaceArgs;
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 Workspace("example", WorkspaceArgs.builder()
            .alias("example")
            .tags(Map.of("Environment", "production"))
            .build());

    }
}
resources:
  example:
    type: aws:amp:Workspace
    properties:
      alias: example
      tags:
        Environment: production

The alias property provides a friendly name for the workspace, making it easier to identify in the AWS console and API responses. The tags property adds key-value metadata for cost allocation and resource organization. Without additional configuration, the workspace uses AWS-owned encryption keys and no CloudWatch logging.

Send workspace logs to CloudWatch

Teams that need visibility into workspace operations configure CloudWatch logging to capture query execution and ingestion errors.

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

const example = new aws.cloudwatch.LogGroup("example", {name: "example"});
const exampleWorkspace = new aws.amp.Workspace("example", {loggingConfiguration: {
    logGroupArn: pulumi.interpolate`${example.arn}:*`,
}});
import pulumi
import pulumi_aws as aws

example = aws.cloudwatch.LogGroup("example", name="example")
example_workspace = aws.amp.Workspace("example", logging_configuration={
    "log_group_arn": example.arn.apply(lambda arn: f"{arn}:*"),
})
package main

import (
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/amp"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		example, err := cloudwatch.NewLogGroup(ctx, "example", &cloudwatch.LogGroupArgs{
			Name: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		_, err = amp.NewWorkspace(ctx, "example", &amp.WorkspaceArgs{
			LoggingConfiguration: &amp.WorkspaceLoggingConfigurationArgs{
				LogGroupArn: example.Arn.ApplyT(func(arn string) (string, error) {
					return fmt.Sprintf("%v:*", arn), nil
				}).(pulumi.StringOutput),
			},
		})
		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.CloudWatch.LogGroup("example", new()
    {
        Name = "example",
    });

    var exampleWorkspace = new Aws.Amp.Workspace("example", new()
    {
        LoggingConfiguration = new Aws.Amp.Inputs.WorkspaceLoggingConfigurationArgs
        {
            LogGroupArn = example.Arn.Apply(arn => $"{arn}:*"),
        },
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.LogGroup;
import com.pulumi.aws.cloudwatch.LogGroupArgs;
import com.pulumi.aws.amp.Workspace;
import com.pulumi.aws.amp.WorkspaceArgs;
import com.pulumi.aws.amp.inputs.WorkspaceLoggingConfigurationArgs;
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 LogGroup("example", LogGroupArgs.builder()
            .name("example")
            .build());

        var exampleWorkspace = new Workspace("exampleWorkspace", WorkspaceArgs.builder()
            .loggingConfiguration(WorkspaceLoggingConfigurationArgs.builder()
                .logGroupArn(example.arn().applyValue(_arn -> String.format("%s:*", _arn)))
                .build())
            .build());

    }
}
resources:
  example:
    type: aws:cloudwatch:LogGroup
    properties:
      name: example
  exampleWorkspace:
    type: aws:amp:Workspace
    name: example
    properties:
      loggingConfiguration:
        logGroupArn: ${example.arn}:*

The loggingConfiguration property directs operational logs to a CloudWatch log group. The logGroupArn must include the :* suffix to allow AMP to create log streams. This captures query execution details, ingestion errors, and other operational events for troubleshooting.

Encrypt workspace data with customer-managed keys

Organizations with compliance requirements use customer-managed KMS keys to control encryption of metrics data.

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

const exampleKey = new aws.kms.Key("example", {
    description: "example",
    deletionWindowInDays: 7,
});
const example = new aws.amp.Workspace("example", {
    alias: "example",
    kmsKeyArn: exampleKey.arn,
});
import pulumi
import pulumi_aws as aws

example_key = aws.kms.Key("example",
    description="example",
    deletion_window_in_days=7)
example = aws.amp.Workspace("example",
    alias="example",
    kms_key_arn=example_key.arn)
package main

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

func main() {
	pulumi.Run(func(ctx *pulumi.Context) error {
		exampleKey, err := kms.NewKey(ctx, "example", &kms.KeyArgs{
			Description:          pulumi.String("example"),
			DeletionWindowInDays: pulumi.Int(7),
		})
		if err != nil {
			return err
		}
		_, err = amp.NewWorkspace(ctx, "example", &amp.WorkspaceArgs{
			Alias:     pulumi.String("example"),
			KmsKeyArn: exampleKey.Arn,
		})
		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 exampleKey = new Aws.Kms.Key("example", new()
    {
        Description = "example",
        DeletionWindowInDays = 7,
    });

    var example = new Aws.Amp.Workspace("example", new()
    {
        Alias = "example",
        KmsKeyArn = exampleKey.Arn,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.amp.Workspace;
import com.pulumi.aws.amp.WorkspaceArgs;
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 exampleKey = new Key("exampleKey", KeyArgs.builder()
            .description("example")
            .deletionWindowInDays(7)
            .build());

        var example = new Workspace("example", WorkspaceArgs.builder()
            .alias("example")
            .kmsKeyArn(exampleKey.arn())
            .build());

    }
}
resources:
  example:
    type: aws:amp:Workspace
    properties:
      alias: example
      kmsKeyArn: ${exampleKey.arn}
  exampleKey:
    type: aws:kms:Key
    name: example
    properties:
      description: example
      deletionWindowInDays: 7

The kmsKeyArn property specifies a customer-managed KMS key for encrypting metrics data at rest. This gives you control over key rotation, access policies, and audit trails. Note that kmsKeyArn is immutable; you cannot change the encryption key after workspace creation.

Beyond these examples

These snippets focus on specific workspace-level features: workspace naming and tagging, CloudWatch logging integration, and customer-managed encryption keys. They’re intentionally minimal rather than full monitoring solutions.

The examples may reference pre-existing infrastructure such as CloudWatch log groups for logging configuration, and KMS keys for encryption configuration. They focus on configuring the workspace rather than provisioning everything around it.

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

  • Prometheus remote write configuration
  • Alert manager configuration
  • Query and ingestion rate limits
  • VPC endpoint configuration for private access

These omissions are intentional: the goal is to illustrate how each workspace feature is wired, not provide drop-in monitoring modules. See the AMP Workspace resource reference for all available configuration options.

Let's create AWS Managed Service for Prometheus Workspaces

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Encryption & Security
Can I change the encryption key after creating a workspace?
No, the kmsKeyArn property is immutable. Choose your encryption strategy before creating the workspace.
What encryption does AMP use by default?
If you don’t provide a kmsKeyArn, AWS uses an AWS owned encryption key to encrypt workspace data.
How do I use my own KMS key for encryption?
Set the kmsKeyArn property to your customer managed KMS key ARN when creating the workspace.
Logging & Monitoring
How do I enable CloudWatch logging for my workspace?
Configure loggingConfiguration with a logGroupArn pointing to your CloudWatch log group. The ARN must include a :* suffix, like ${logGroup.arn}:*.
Configuration & Setup
What's the difference between alias and workspace ID?
The alias is an optional friendly name for your workspace, while the workspace ID is the auto-generated identifier used for import and API operations.
How do I get the Prometheus endpoint for my workspace?
The prometheusEndpoint output property provides the endpoint URL after workspace creation.

Using a different cloud?

Explore monitoring guides for other cloud providers: