Create AWS EventBridge Event Archives

The aws:cloudwatch/eventArchive:EventArchive resource, part of the Pulumi AWS provider, captures and stores events from an EventBridge event bus for compliance, debugging, or replay scenarios. This guide focuses on three capabilities: basic event archiving, event filtering with retention policies, and customer-managed key encryption.

Archives capture events from existing EventBridge event buses. The examples are intentionally small. Combine them with your own event buses, filtering logic, and encryption requirements.

Archive all events from a custom event bus

Most archive deployments start by capturing all events from a specific event bus for later retrieval.

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

const order = new aws.cloudwatch.EventBus("order", {name: "orders"});
const orderEventArchive = new aws.cloudwatch.EventArchive("order", {
    name: "order-archive",
    eventSourceArn: order.arn,
});
import pulumi
import pulumi_aws as aws

order = aws.cloudwatch.EventBus("order", name="orders")
order_event_archive = aws.cloudwatch.EventArchive("order",
    name="order-archive",
    event_source_arn=order.arn)
package main

import (
	"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 {
		order, err := cloudwatch.NewEventBus(ctx, "order", &cloudwatch.EventBusArgs{
			Name: pulumi.String("orders"),
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventArchive(ctx, "order", &cloudwatch.EventArchiveArgs{
			Name:           pulumi.String("order-archive"),
			EventSourceArn: order.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 order = new Aws.CloudWatch.EventBus("order", new()
    {
        Name = "orders",
    });

    var orderEventArchive = new Aws.CloudWatch.EventArchive("order", new()
    {
        Name = "order-archive",
        EventSourceArn = order.Arn,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.EventBus;
import com.pulumi.aws.cloudwatch.EventBusArgs;
import com.pulumi.aws.cloudwatch.EventArchive;
import com.pulumi.aws.cloudwatch.EventArchiveArgs;
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 order = new EventBus("order", EventBusArgs.builder()
            .name("orders")
            .build());

        var orderEventArchive = new EventArchive("orderEventArchive", EventArchiveArgs.builder()
            .name("order-archive")
            .eventSourceArn(order.arn())
            .build());

    }
}
resources:
  order:
    type: aws:cloudwatch:EventBus
    properties:
      name: orders
  orderEventArchive:
    type: aws:cloudwatch:EventArchive
    name: order
    properties:
      name: order-archive
      eventSourceArn: ${order.arn}

The eventSourceArn property specifies which event bus to archive from; only events published to that bus are captured. By default, the archive stores every event indefinitely without filtering or expiration.

Filter and retain events for a limited period

Not all events need permanent storage. You can archive only specific event types and apply retention policies to manage costs.

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

const order = new aws.cloudwatch.EventBus("order", {name: "orders"});
const orderEventArchive = new aws.cloudwatch.EventArchive("order", {
    name: "order-archive",
    description: "Archived events from order service",
    eventSourceArn: order.arn,
    retentionDays: 7,
    eventPattern: JSON.stringify({
        source: ["company.team.order"],
    }),
});
import pulumi
import json
import pulumi_aws as aws

order = aws.cloudwatch.EventBus("order", name="orders")
order_event_archive = aws.cloudwatch.EventArchive("order",
    name="order-archive",
    description="Archived events from order service",
    event_source_arn=order.arn,
    retention_days=7,
    event_pattern=json.dumps({
        "source": ["company.team.order"],
    }))
package main

import (
	"encoding/json"

	"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 {
		order, err := cloudwatch.NewEventBus(ctx, "order", &cloudwatch.EventBusArgs{
			Name: pulumi.String("orders"),
		})
		if err != nil {
			return err
		}
		tmpJSON0, err := json.Marshal(map[string]interface{}{
			"source": []string{
				"company.team.order",
			},
		})
		if err != nil {
			return err
		}
		json0 := string(tmpJSON0)
		_, err = cloudwatch.NewEventArchive(ctx, "order", &cloudwatch.EventArchiveArgs{
			Name:           pulumi.String("order-archive"),
			Description:    pulumi.String("Archived events from order service"),
			EventSourceArn: order.Arn,
			RetentionDays:  pulumi.Int(7),
			EventPattern:   pulumi.String(json0),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var order = new Aws.CloudWatch.EventBus("order", new()
    {
        Name = "orders",
    });

    var orderEventArchive = new Aws.CloudWatch.EventArchive("order", new()
    {
        Name = "order-archive",
        Description = "Archived events from order service",
        EventSourceArn = order.Arn,
        RetentionDays = 7,
        EventPattern = JsonSerializer.Serialize(new Dictionary<string, object?>
        {
            ["source"] = new[]
            {
                "company.team.order",
            },
        }),
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.EventBus;
import com.pulumi.aws.cloudwatch.EventBusArgs;
import com.pulumi.aws.cloudwatch.EventArchive;
import com.pulumi.aws.cloudwatch.EventArchiveArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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 order = new EventBus("order", EventBusArgs.builder()
            .name("orders")
            .build());

        var orderEventArchive = new EventArchive("orderEventArchive", EventArchiveArgs.builder()
            .name("order-archive")
            .description("Archived events from order service")
            .eventSourceArn(order.arn())
            .retentionDays(7)
            .eventPattern(serializeJson(
                jsonObject(
                    jsonProperty("source", jsonArray("company.team.order"))
                )))
            .build());

    }
}
resources:
  order:
    type: aws:cloudwatch:EventBus
    properties:
      name: orders
  orderEventArchive:
    type: aws:cloudwatch:EventArchive
    name: order
    properties:
      name: order-archive
      description: Archived events from order service
      eventSourceArn: ${order.arn}
      retentionDays: 7
      eventPattern:
        fn::toJSON:
          source:
            - company.team.order

The eventPattern property filters which events to capture using the same JSON pattern syntax as EventBridge rules. Here, only events with source “company.team.order” are archived. The retentionDays property sets automatic expiration; after 7 days, events are deleted from the archive.

Encrypt archived events with customer-managed keys

Compliance requirements often mandate encryption with customer-managed KMS keys rather than AWS-managed encryption.

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

const current = aws.getCallerIdentity({});
const currentGetPartition = aws.getPartition({});
const example = new aws.cloudwatch.EventBus("example", {name: "example"});
const exampleKey = new aws.kms.Key("example", {
    deletionWindowInDays: 7,
    policy: pulumi.jsonStringify({
        Version: "2012-10-17",
        Id: "key-policy-example",
        Statement: [
            {
                Sid: "Enable IAM User Permissions",
                Effect: "Allow",
                Principal: {
                    AWS: Promise.all([currentGetPartition, current]).then(([currentGetPartition, current]) => `arn:${currentGetPartition.partition}:iam::${current.accountId}:root`),
                },
                Action: "kms:*",
                Resource: "*",
            },
            {
                Sid: "Allow describing of the key",
                Effect: "Allow",
                Principal: {
                    Service: "events.amazonaws.com",
                },
                Action: ["kms:DescribeKey"],
                Resource: "*",
            },
            {
                Sid: "Allow use of the key",
                Effect: "Allow",
                Principal: {
                    Service: "events.amazonaws.com",
                },
                Action: [
                    "kms:GenerateDataKey",
                    "kms:Decrypt",
                    "kms:ReEncrypt*",
                ],
                Resource: "*",
                Condition: {
                    StringEquals: {
                        "kms:EncryptionContext:aws:events:event-bus:arn": example.arn,
                    },
                },
            },
        ],
    }),
    tags: {
        EventBridgeApiDestinations: "true",
    },
});
const exampleEventArchive = new aws.cloudwatch.EventArchive("example", {
    name: "example",
    eventSourceArn: example.arn,
    kmsKeyIdentifier: exampleKey.id,
});
import pulumi
import json
import pulumi_aws as aws

current = aws.get_caller_identity()
current_get_partition = aws.get_partition()
example = aws.cloudwatch.EventBus("example", name="example")
example_key = aws.kms.Key("example",
    deletion_window_in_days=7,
    policy=pulumi.Output.json_dumps({
        "Version": "2012-10-17",
        "Id": "key-policy-example",
        "Statement": [
            {
                "Sid": "Enable IAM User Permissions",
                "Effect": "Allow",
                "Principal": {
                    "AWS": f"arn:{current_get_partition.partition}:iam::{current.account_id}:root",
                },
                "Action": "kms:*",
                "Resource": "*",
            },
            {
                "Sid": "Allow describing of the key",
                "Effect": "Allow",
                "Principal": {
                    "Service": "events.amazonaws.com",
                },
                "Action": ["kms:DescribeKey"],
                "Resource": "*",
            },
            {
                "Sid": "Allow use of the key",
                "Effect": "Allow",
                "Principal": {
                    "Service": "events.amazonaws.com",
                },
                "Action": [
                    "kms:GenerateDataKey",
                    "kms:Decrypt",
                    "kms:ReEncrypt*",
                ],
                "Resource": "*",
                "Condition": {
                    "StringEquals": {
                        "kms:EncryptionContext:aws:events:event-bus:arn": example.arn,
                    },
                },
            },
        ],
    }),
    tags={
        "EventBridgeApiDestinations": "true",
    })
example_event_archive = aws.cloudwatch.EventArchive("example",
    name="example",
    event_source_arn=example.arn,
    kms_key_identifier=example_key.id)
package main

import (
	"encoding/json"
	"fmt"

	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws"
	"github.com/pulumi/pulumi-aws/sdk/v7/go/aws/cloudwatch"
	"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 {
		current, err := aws.GetCallerIdentity(ctx, &aws.GetCallerIdentityArgs{}, nil)
		if err != nil {
			return err
		}
		currentGetPartition, err := aws.GetPartition(ctx, &aws.GetPartitionArgs{}, nil)
		if err != nil {
			return err
		}
		example, err := cloudwatch.NewEventBus(ctx, "example", &cloudwatch.EventBusArgs{
			Name: pulumi.String("example"),
		})
		if err != nil {
			return err
		}
		exampleKey, err := kms.NewKey(ctx, "example", &kms.KeyArgs{
			DeletionWindowInDays: pulumi.Int(7),
			Policy: example.Arn.ApplyT(func(arn string) (pulumi.String, error) {
				var _zero pulumi.String
				tmpJSON0, err := json.Marshal(map[string]interface{}{
					"Version": "2012-10-17",
					"Id":      "key-policy-example",
					"Statement": []interface{}{
						map[string]interface{}{
							"Sid":    "Enable IAM User Permissions",
							"Effect": "Allow",
							"Principal": map[string]interface{}{
								"AWS": fmt.Sprintf("arn:%v:iam::%v:root", currentGetPartition.Partition, current.AccountId),
							},
							"Action":   "kms:*",
							"Resource": "*",
						},
						map[string]interface{}{
							"Sid":    "Allow describing of the key",
							"Effect": "Allow",
							"Principal": map[string]interface{}{
								"Service": "events.amazonaws.com",
							},
							"Action": []string{
								"kms:DescribeKey",
							},
							"Resource": "*",
						},
						map[string]interface{}{
							"Sid":    "Allow use of the key",
							"Effect": "Allow",
							"Principal": map[string]interface{}{
								"Service": "events.amazonaws.com",
							},
							"Action": []string{
								"kms:GenerateDataKey",
								"kms:Decrypt",
								"kms:ReEncrypt*",
							},
							"Resource": "*",
							"Condition": map[string]interface{}{
								"StringEquals": map[string]interface{}{
									"kms:EncryptionContext:aws:events:event-bus:arn": arn,
								},
							},
						},
					},
				})
				if err != nil {
					return _zero, err
				}
				json0 := string(tmpJSON0)
				return pulumi.String(json0), nil
			}).(pulumi.StringOutput),
			Tags: pulumi.StringMap{
				"EventBridgeApiDestinations": pulumi.String("true"),
			},
		})
		if err != nil {
			return err
		}
		_, err = cloudwatch.NewEventArchive(ctx, "example", &cloudwatch.EventArchiveArgs{
			Name:             pulumi.String("example"),
			EventSourceArn:   example.Arn,
			KmsKeyIdentifier: exampleKey.ID(),
		})
		if err != nil {
			return err
		}
		return nil
	})
}
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using Pulumi;
using Aws = Pulumi.Aws;

return await Deployment.RunAsync(() => 
{
    var current = Aws.GetCallerIdentity.Invoke();

    var currentGetPartition = Aws.GetPartition.Invoke();

    var example = new Aws.CloudWatch.EventBus("example", new()
    {
        Name = "example",
    });

    var exampleKey = new Aws.Kms.Key("example", new()
    {
        DeletionWindowInDays = 7,
        Policy = Output.JsonSerialize(Output.Create(new Dictionary<string, object?>
        {
            ["Version"] = "2012-10-17",
            ["Id"] = "key-policy-example",
            ["Statement"] = new[]
            {
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Enable IAM User Permissions",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["AWS"] = Output.Tuple(currentGetPartition, current).Apply(values =>
                        {
                            var currentGetPartition = values.Item1;
                            var current = values.Item2;
                            return $"arn:{currentGetPartition.Apply(getPartitionResult => getPartitionResult.Partition)}:iam::{current.Apply(getCallerIdentityResult => getCallerIdentityResult.AccountId)}:root";
                        }),
                    },
                    ["Action"] = "kms:*",
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow describing of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["Service"] = "events.amazonaws.com",
                    },
                    ["Action"] = new[]
                    {
                        "kms:DescribeKey",
                    },
                    ["Resource"] = "*",
                },
                new Dictionary<string, object?>
                {
                    ["Sid"] = "Allow use of the key",
                    ["Effect"] = "Allow",
                    ["Principal"] = new Dictionary<string, object?>
                    {
                        ["Service"] = "events.amazonaws.com",
                    },
                    ["Action"] = new[]
                    {
                        "kms:GenerateDataKey",
                        "kms:Decrypt",
                        "kms:ReEncrypt*",
                    },
                    ["Resource"] = "*",
                    ["Condition"] = new Dictionary<string, object?>
                    {
                        ["StringEquals"] = new Dictionary<string, object?>
                        {
                            ["kms:EncryptionContext:aws:events:event-bus:arn"] = example.Arn,
                        },
                    },
                },
            },
        })),
        Tags = 
        {
            { "EventBridgeApiDestinations", "true" },
        },
    });

    var exampleEventArchive = new Aws.CloudWatch.EventArchive("example", new()
    {
        Name = "example",
        EventSourceArn = example.Arn,
        KmsKeyIdentifier = exampleKey.Id,
    });

});
package generated_program;

import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetCallerIdentityArgs;
import com.pulumi.aws.inputs.GetPartitionArgs;
import com.pulumi.aws.cloudwatch.EventBus;
import com.pulumi.aws.cloudwatch.EventBusArgs;
import com.pulumi.aws.kms.Key;
import com.pulumi.aws.kms.KeyArgs;
import com.pulumi.aws.cloudwatch.EventArchive;
import com.pulumi.aws.cloudwatch.EventArchiveArgs;
import static com.pulumi.codegen.internal.Serialization.*;
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) {
        final var current = AwsFunctions.getCallerIdentity(GetCallerIdentityArgs.builder()
            .build());

        final var currentGetPartition = AwsFunctions.getPartition(GetPartitionArgs.builder()
            .build());

        var example = new EventBus("example", EventBusArgs.builder()
            .name("example")
            .build());

        var exampleKey = new Key("exampleKey", KeyArgs.builder()
            .deletionWindowInDays(7)
            .policy(example.arn().applyValue(_arn -> serializeJson(
                jsonObject(
                    jsonProperty("Version", "2012-10-17"),
                    jsonProperty("Id", "key-policy-example"),
                    jsonProperty("Statement", jsonArray(
                        jsonObject(
                            jsonProperty("Sid", "Enable IAM User Permissions"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("AWS", String.format("arn:%s:iam::%s:root", currentGetPartition.partition(),current.accountId()))
                            )),
                            jsonProperty("Action", "kms:*"),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow describing of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("Service", "events.amazonaws.com")
                            )),
                            jsonProperty("Action", jsonArray("kms:DescribeKey")),
                            jsonProperty("Resource", "*")
                        ), 
                        jsonObject(
                            jsonProperty("Sid", "Allow use of the key"),
                            jsonProperty("Effect", "Allow"),
                            jsonProperty("Principal", jsonObject(
                                jsonProperty("Service", "events.amazonaws.com")
                            )),
                            jsonProperty("Action", jsonArray(
                                "kms:GenerateDataKey", 
                                "kms:Decrypt", 
                                "kms:ReEncrypt*"
                            )),
                            jsonProperty("Resource", "*"),
                            jsonProperty("Condition", jsonObject(
                                jsonProperty("StringEquals", jsonObject(
                                    jsonProperty("kms:EncryptionContext:aws:events:event-bus:arn", _arn)
                                ))
                            ))
                        )
                    ))
                ))))
            .tags(Map.of("EventBridgeApiDestinations", "true"))
            .build());

        var exampleEventArchive = new EventArchive("exampleEventArchive", EventArchiveArgs.builder()
            .name("example")
            .eventSourceArn(example.arn())
            .kmsKeyIdentifier(exampleKey.id())
            .build());

    }
}
resources:
  example:
    type: aws:cloudwatch:EventBus
    properties:
      name: example
  exampleKey:
    type: aws:kms:Key
    name: example
    properties:
      deletionWindowInDays: 7
      policy:
        fn::toJSON:
          Version: 2012-10-17
          Id: key-policy-example
          Statement:
            - Sid: Enable IAM User Permissions
              Effect: Allow
              Principal:
                AWS: arn:${currentGetPartition.partition}:iam::${current.accountId}:root
              Action: kms:*
              Resource: '*'
            - Sid: Allow describing of the key
              Effect: Allow
              Principal:
                Service: events.amazonaws.com
              Action:
                - kms:DescribeKey
              Resource: '*'
            - Sid: Allow use of the key
              Effect: Allow
              Principal:
                Service: events.amazonaws.com
              Action:
                - kms:GenerateDataKey
                - kms:Decrypt
                - kms:ReEncrypt*
              Resource: '*'
              Condition:
                StringEquals:
                  kms:EncryptionContext:aws:events:event-bus:arn: ${example.arn}
      tags:
        EventBridgeApiDestinations: 'true'
  exampleEventArchive:
    type: aws:cloudwatch:EventArchive
    name: example
    properties:
      name: example
      eventSourceArn: ${example.arn}
      kmsKeyIdentifier: ${exampleKey.id}
variables:
  current:
    fn::invoke:
      function: aws:getCallerIdentity
      arguments: {}
  currentGetPartition:
    fn::invoke:
      function: aws:getPartition
      arguments: {}

The kmsKeyIdentifier property specifies a customer-managed KMS key for encryption. The KMS key policy must grant EventBridge permissions for DescribeKey, GenerateDataKey, Decrypt, and ReEncrypt operations. The policy uses encryption context to scope permissions to the specific event bus ARN, ensuring the key can only be used for this archive.

Beyond these examples

These snippets focus on specific archive-level features: event capture and filtering, retention policies, and customer-managed encryption. They’re intentionally minimal rather than full event-driven architectures.

The examples reference pre-existing infrastructure such as EventBridge event buses, and KMS keys with appropriate policies for the encryption example. They focus on configuring the archive rather than provisioning the surrounding event infrastructure.

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

  • Archive replay to event buses
  • Cross-region archive replication
  • Archive monitoring and metrics
  • IAM permissions for archive access

These omissions are intentional: the goal is to illustrate how each archive feature is wired, not provide drop-in event storage modules. See the EventBridge EventArchive resource reference for all available configuration options.

Let's create AWS EventBridge Event Archives

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

Try Pulumi Cloud for FREE

Frequently Asked Questions

Configuration & Limits
What properties can't be changed after creating an archive?
Both eventSourceArn and name are immutable. Changing either property forces recreation of the archive.
What's the maximum length for an archive name?
Archive names cannot exceed 48 characters.
How long are events retained by default?
Archives retain events indefinitely by default. Use retentionDays to set a maximum retention period.
What's the difference between EventBridge and CloudWatch Events?
EventBridge was formerly known as CloudWatch Events. The functionality is identical.
Event Filtering & Archiving
How do I filter which events get archived?
Use eventPattern with a JSON filter to select specific events. Without a pattern, all events from the event bus are archived.
Can I archive events from multiple event buses?
No, each archive is associated with a single event bus via eventSourceArn. Only events from that bus are archived.
Encryption & Security
What KMS permissions are required for archive encryption?
The KMS key policy must allow events.amazonaws.com to perform kms:DescribeKey, kms:GenerateDataKey, kms:Decrypt, and kms:ReEncrypt*. Include a condition that matches the event bus ARN in the encryption context: kms:EncryptionContext:aws:events:event-bus:arn.
What types of KMS key identifiers can I use?
You can use the key ARN, KeyId, key alias, or key alias ARN as the kmsKeyIdentifier.
Is encryption enabled by default?
No, encryption is optional. Specify kmsKeyIdentifier to encrypt the archive with a customer managed KMS key.

Using a different cloud?

Explore messaging guides for other cloud providers: