A step-by-step guide to cross-account and cross-region events with EventBridge

Antonio Lagrotteria
6 min readMay 19, 2023

Event-driven architectures (EDAs) have revolutionized how software systems are built, enabling efficient communication, low coupling and scalability.

However, managing events across multiple accounts and regions has traditionally been complex and challenging. That is where EventBridge comes in.

This article provides a step-by-step guide on how EventBridge simplifies orchestrating event-driven architectures, enabling cross-account and cross-region event routing.

The article is also available on Re:Post:

Architecture

The architecture involves three accounts:

  • AccountA: the source event account with a Lambda function that sends events.
  • AccountGlobal: the account hosting the global Event bus and forwarding rule to the target account.
  • AccountB, the target event account containing our target workload, a Lambda function.

The flow has four steps:

  1. EventSender Lambda is triggered.
  2. EventSender Lambda sends an event towards the global event bus.
  3. Global event bus forwards the event to a target event bus.
  4. The target event bus forwards the event to Event Receiver Lambda.

Prerequisite: Multi-account setup via Organizations

The easiest way to set up accounts is via AWS Organizations.

  • Go to AWS Organizations and create an Organization
  • Start adding or inviting AWS accounts
  • Create AccountA, AccountB and AccountGlobal similarly.
  • Optionally, you can place the accounts under Organizational Units (OUs) for better management.
  • The Organizational structure should look as this.

For tutorials/troubleshooting on AWS Organizations (out of the scope of this article), please refer to the following:

Finally, please take note of the respective AWS account ids, and let’s start the steps.

Steps

1. Setup Global Account

  • Login to AccountGlobal
  • Select Ireland region (eu-west-1)
  • In EventBridge, create a custom Event bus named event-bus-global
  • Associate following Resource-based policy and replace placeholders with correct AWS account IDs:
{
"Version": "2012–10–17",
"Statement": [{
"Sid": "allow_account_a_to_put_events",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_A_ID>:root"
},
"Action": "events:PutEvents",
"Resource": "arn:aws:events:eu-west-1:<ACCOUNT_GLOBAL_ID>:event-bus/event-bus-global"
}]
}
  • If you experience issues with the above, click Load template and modify accordingly:
  • Click Create, and the custom bus is created.
  • Take note of the event bus Amazon Resource Name (ARN).

2. Setup Account A (Sender)

  • Login to AccountA
  • Select Ireland region (eu-west-1)
  • In Lambda, create a NodeJS 18.x Lambda Function called eventSender
  • Add the following code. The code leverages the AWS SDK EventBridge client library to send a trivial JSON payload to the global Event bus, identified by its ARN. Event “Source” and “DetailType” will be used later to filter the event and forward it to appropriate targets.
import { EventBridgeClient, PutEventsCommand } from “@aws-sdk/client-eventbridge”;

export const handler = async(event) => {
try {
const eventBridge = new EventBridgeClient({ region: ‘eu-west-1’ });
const eventParams = {
Entries: [
{
Source: ‘event.sender.source’,
DetailType: ‘EventA.Sent’,
Detail: JSON.stringify({ type: ‘a’, value: ‘111’ }),
EventBusName: ‘arn:aws:events:eu-west-1:<ACCOUNT_GLOBAL_ID>:event-bus/event-bus-global’
}
]
};

await eventBridge.send(new PutEventsCommand(eventParams));

return {
statusCode: 200,
body: ‘Event sent successfully’
};
} catch (err) {
console.error(‘Failed to send event:’, err);

return {
statusCode: 500,
body: ‘Failed to send event’
};
}
};
  • Under Configuration -> Permissions, click on the IAM execution role and add the following custom policy to the role:
{
“Version”: “2012–10–17”,
“Statement”: [
{
“Effect”: “Allow”,
“Action”: [“events:PutEvents”],
“Resource”: [
“arn:aws:events:eu-west-1:<ACCOUNT_GLOBAL_ID>:event-bus/event-bus-global”
]
}
]
}

3. Setup Account B (Receiver)

  • Login to AccountB
  • In EventBridge, create a custom Event Bus named event-bus-account-b in a different region than AccountA bus and sender, e.g. Stockholm (eu-north-1)
  • Associate following Resource-based policy:
{
"Version": "2012–10–17",
"Statement": [{
"Sid": "allow_account_to_put_events",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::<ACCOUNT_GLOBAL_ID>:root"
},
"Action": "events:PutEvents",
"Resource": "arn:aws:events:eu-north-1:<ACCOUNT_B_ID>:event-bus/event-bus-account-b"
}]
}
  • In Lambda, create a NodeJS 18.x Lambda function, as usual, called EventReceiver:
export const handler = async(event) => {
console.log(“Event received: “, event);

const response = {
statusCode: 200,
body: JSON.stringify(‘Hello from Lambda!’),
};

return response;
};

4. Glue the accounts via Rules

Now it is time to use EventBridge rules to link events between accounts. We will need two rules.

4.1 Setup the rule in the global account

  • In AccountGlobal, create an event rule named global-to-account-b, associated with the custom event bus (not the default one).
  • Select the Creation method “Custom pattern (JSON editor)” during the wizard and create the following Event Pattern, which matches any event coming from the source and detail type sent from the Lambda EventSender, in AccountA.
{
“source”: [“event.sender.source”],
“detail-type”: [“EventA.Sent”]
}
  • The target type is another EventBridge event bus (event-bus-account-b), which lives in a different account and a different region (eu-north-1) than the global one (eu-west-1). Pick the event bus ARN from AccountB.
  • Move forward and Create the rule.

4.2 Setup the rule in the AccountB

  • In AccountB, create an event rule named account-b-to-target, associated with the custom event bus (not the default one),
  • Fill same Event Pattern as the previous step above.
  • This time, the target type is the Lambda function, named EventReceiver, previously created in AccountB.
  • Move forward until the rule is created.

Verification

To verify that EventSender in AccountA (eu-west-1) sends an event to EventReceiver in AccountB (eu-north-1) via a global bus (eu-west-1), trigger the EventSender lambda function.

In AccountB, go to the CloudWatch log group associated with the target function (EventReceiver), and the following log will prove the event's successful reception across accounts and regions.

Summary

In conclusion, this article demonstrated that EventBridge’s cross-account and cross-region event capabilities provide a straightforward and efficient solution for managing workloads and orchestrating event-driven architectures.

As the next step, implement the above via IaC, such as CDK, have fun!

--

--

Antonio Lagrotteria

Engineering Manager | Full-Stack Architect | Team/Tech Lead with a passion for frontend, backend and cloud | AWS Community Builder