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 FREEFrequently Asked Questions
Configuration & Limits
eventSourceArn and name are immutable. Changing either property forces recreation of the archive.retentionDays to set a maximum retention period.Event Filtering & Archiving
eventPattern with a JSON filter to select specific events. Without a pattern, all events from the event bus are archived.eventSourceArn. Only events from that bus are archived.Encryption & Security
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.kmsKeyIdentifier.kmsKeyIdentifier to encrypt the archive with a customer managed KMS key.Using a different cloud?
Explore messaging guides for other cloud providers: