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 archival, event filtering with retention policies, and customer-managed encryption.
Archives reference existing EventBridge event buses and optionally KMS keys for encryption. 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
Teams building event-driven architectures often need to preserve event history for compliance, debugging, or replay scenarios.
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. Without an eventPattern, the archive stores every event. Without retentionDays, events are kept indefinitely.
Filter and retain events for a limited period
Not all events need permanent storage. Applications often archive only specific event types and apply retention policies to manage storage 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 archive using the same JSON syntax as EventBridge rules. Here, only events with source “company.team.order” are stored. The retentionDays property automatically deletes events after 7 days, reducing storage costs.
Encrypt archived events with a customer-managed key
Compliance requirements often mandate encryption of archived data using organization-managed 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 key policy must grant EventBridge permissions for DescribeKey, GenerateDataKey, Decrypt, and ReEncrypt operations. The policy condition ties encryption to the specific event bus ARN, ensuring the key is only used for this archive.
Beyond these examples
These snippets focus on specific archive-level features: event filtering and 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 lifecycle policies beyond retention days
- 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 FREEFrequently Asked Questions
Configuration & Limits
name and eventSourceArn properties are immutable and cannot be changed after creation. Modifying either requires recreating the archive.Event Filtering & Retention
retentionDays to specify a maximum retention period.eventSourceArn.eventPattern property to specify an event pattern that filters which events get sent to the archive.Encryption & Security
kmsKeyIdentifier to your KMS key ARN, KeyId, key alias, or key alias ARN. Ensure your KMS key policy grants EventBridge the necessary permissions.kms:DescribeKey on all resources, plus kms:GenerateDataKey, kms:Decrypt, and kms:ReEncrypt* with a condition that matches your event bus ARN in the encryption context.kmsKeyIdentifier accepts the key ARN, KeyId, key alias, or key alias ARN.Using a different cloud?
Explore messaging guides for other cloud providers: