Introduction
AWS EventBridge is a powerful event bus that allows seamless integration between AWS services and external systems. However, one common challenge is that EventBridge events are typically JSON payloads that, while structured, can be difficult to read at a glance—especially when sent to destinations like Amazon SNS for alerting. This can be a pain point for teams, particularly in Managed Services, where help desk staff need to interpret alerts and take action quickly.
Fortunately, EventBridge Transforms offers a solution by allowing us to modify event payloads into a more human-readable format before they reach their destination. In this post, I'll walk through how EventBridge transforms work, provide a hands-on guide to implementing them, and share best practices from real-world use cases.
Understanding EventBridge Transforms
EventBridge transforms allow you to modify event payloads before sending them to targets. Instead of passing raw JSON, you can extract and format key details, making the message easier to read.
Example Problem: Raw JSON payload
Consider an EventBridge event triggered by an AWS resource:
{"version":"0","id":"c8c4daa7-a20c-2f03-0070-b7393dd542ad","detail-type":"GuardDuty Finding","source":"aws.guardduty","account":"123456789012","time":"1970-01-01T00:00:00Z","region":"us-east-1","resources":[],"detail":{"schemaVersion":"2.0","accountId":"123456789012","region":"us-east-1","partition":"aws","id":"16afba5c5c43e07c9e3e5e2e544e95df","arn":"arn:aws:guardduty:us-east-1:123456789012:detector/123456789012/finding/16afba5c5c43e07c9e3e5e2e544e95df","type":"Canary:EC2/Stateless.IntegTest","resource":{"resourceType":"Instance","instanceDetails":{"instanceId":"i-05746eb48123455e0","instanceType":"t2.micro","launchTime":1492735675000,"productCodes":[],"networkInterfaces":[{"ipv6Addresses":[],"privateDnsName":"ip-0-0-0-0.us-east-1.compute.internal","privateIpAddress":"0.0.0.0","privateIpAddresses":[{"privateDnsName":"ip-0-0-0-0.us-east-1.compute.internal","privateIpAddress":"0.0.0.0"}],"subnetId":"subnet-d58b7123","vpcId":"vpc-34865123","securityGroups":[{"groupName":"launch-wizard-1","groupId":"sg-9918a123"}],"publicDnsName":"ec2-11-111-111-1.us-east-1.compute.amazonaws.com","publicIp":"11.111.111.1"}],"tags":[{"key":"Name","value":"ssh-22-open"}],"instanceState":"running","availabilityZone":"us-east-1b","imageId":"ami-4836a123","imageDescription":"Amazon Linux AMI 2017.03.0.20170417 x86_64 HVM GP2"}},"service":{"serviceName":"guardduty","detectorId":"3caf4e0aaa46ce4ccbcef949a8785353","action":{"actionType":"NETWORK_CONNECTION","networkConnectionAction":{"connectionDirection":"OUTBOUND","remoteIpDetails":{"ipAddressV4":"0.0.0.0","organization":{"asn":-1,"isp":"GeneratedFindingISP","org":"GeneratedFindingORG"},"country":{"countryName":"United States"},"city":{"cityName":"GeneratedFindingCityName"},"geoLocation":{"lat":0,"lon":0}},"remotePortDetails":{"port":22,"portName":"SSH"},"localPortDetails":{"port":2000,"portName":"Unknown"},"protocol":"TCP","blocked":false}},"resourceRole":"TARGET","additionalInfo":{"unusualProtocol":"UDP","threatListName":"GeneratedFindingCustomerListName","unusual":22},"eventFirstSeen":"2017-10-31T23:16:23Z","eventLastSeen":"2017-10-31T23:16:23Z","archived":false,"count":1},"severity":5,"createdAt":"2017-10-31T23:16:23.824Z","updatedAt":"2017-10-31T23:16:23.824Z","title":"Canary:EC2/Stateless.IntegTest","description":"Canary:EC2/Stateless.IntegTest"}}
This is not very intuitive for a help desk operator. They may not be very familiar with AWS, and it isn't easy to work out what fields are meaningful, especially when the JSON is presented as a single line.
Using a Transform to Improve Readability
By applying an EventBridge transform, we can extract only the relevant details and format them into a readable message:
"A Guard Duty finding on severity 5 has been raised for source account 123456789012.”
"The finding was generated at 2025-01-25T06:07:04Z and is DefenseEvasion:EC2/UnusualDNSResolver."
"The affected resource type is Instance."
"Description: The EC2 instance i-045678abc09 is communicating with an unusual DNS resolver 172.123.45.6.”
This makes it immediately clear what the affected account is and what happened, reducing the time needed for triage and response.
Implementing an EventBridge Transform
Let's walk through how to set up an EventBridge rule with a transform using AWS CloudFormation.
CloudFormation Example
Below is an example CloudFormation snippet to create an EventBridge rule with a transform that simplifies GuardDuty finding notifications:
GuardDutyEventRule:
Type: "AWS::Events::Rule"
Properties:
Name: "detect-guardduty-finding"
Description: "A CloudWatch Event Rule that triggers on Amazon GuardDuty findings."
State: "ENABLED"
Targets:
- Arn: !Ref GuardDutySnsTopic
Id: "target-id1"
InputTransformer:
InputPathsMap:
"account": "$.account"
"time": "$.time"
"source-account": "$.detail.accountId"
"finding-type": "$.detail.type"
"resource-type": "$.detail.resource.resourceType"
"severity": "$.detail.severity"
"description": "$.detail.description"
InputTemplate: |
"A Guard Duty finding on severity <severity> has been raised for source account <source-account>."
"The finding was generated at <time> and is <finding-type>."
"The affected resource type is <resource-type>."
"Description: <description>"
EventPattern:
detail-type:
- "GuardDuty Finding"
source:
- "aws.guardduty"
detail:
severity:
- 5
- 6
- 7
- 8
This rule listens for GuardDuty finding notifications, extracts relevant details, and reformats the message into a simple, readable sentence before sending it to an SNS topic.
Testing the Transform in the AWS Console
Jumping straight into CloudFormation is fine if you're comfortable with JSON payload, but most of the time, you don't know exactly what you want to do. AWS provides a way to test and view event transforms directly in the EventBridge console. Here’s how you can do it:
Go to Rules
Go to the EventBridge Console – Navigate to Amazon EventBridge > Rules.
Choose the Rule
Select or Create a Rule – Choose an existing rule or create a new one.
Create the Transformer
Either click on Edit for the rule, or go to the Targets tab and select Edit there.
Expand the Additional settings section and click the dropdown.
Selecting Input transformer brings up a Configure input transformer button.
Create and test your transform
Now we come to the fun part. Creating and testing the rules!
You can either generate a sample event or paste in one of your own.
This is an optional step, but seeing the JSON that you're dealing with is very helpful.
You can expand the Example section to get some ideas for your Input and Template. This is handy if you've not done this much, after a few times, you'll get the hang of it.
Then, fill in the Input path and Input template. The Input path in a JSON construct with the variables you will use in the human-readable text. These variables are taken from the JSON payload. I don't know why you need this additional step, but you do.
Finally, the Input template section is where you enter the message you want to have sent using the variables from the Input path section.
To see what all that will look like, there is an Output section. For this to work, you need either the sample output or to have Entered your own JSON. This is where having a sample of the non-transformed code can really help. You will see what the result will actually be.
Save and Deploy
Once you're satisfied with the output, save and deploy the rule.
Alternatively, you can use it to update your CloudFormation template. I have included a sample above for you to use as a guide.
There is a third option. Scrolling back to my first image, you'll see a button for CloudFormation Template. Clicking that and selecting YAML (for the love of God, don't choose JSON) will generate a CloudFormation template for you. This is great if you are trying this in a dev account. You can use clickops to create your rule and transform, then have your IaC generated for you.
Why This Matters
In Managed Services, we often route AWS alerts to an SNS topic that integrates with our ticketing system. Initially, we sent raw JSON payloads, which made it difficult for help desk staff to understand incidents quickly.
By implementing EventBridge transforms, we significantly improved the clarity of alerts, reducing response times and improving efficiency. For example, instead of:
{"detail": {"instance-id": "i-12345", "state": "terminated"}}
We now see:
EC2 Instance i-12345 has changed state to terminated.
This small change has a big impact on triaging and response.
Best Practices for Using EventBridge Transforms
Keep It Concise – Extract only the necessary details to avoid clutter. The affected resource should be providing the detailed information, not the alert.
Use Human-Readable Formatting – Avoid technical jargon where possible. This is especially important if the first destination is a help desk.
Test Before Deploying – Use the AWS console to verify transformations.
Consider Multiple Destinations – Tailor transformations based on where the alert goes (e.g., SNS, Lambda, or third-party tools like Slack or PagerDuty). Note: You can only have one transform per target.
Monitor and Iterate – Regularly review and adjust transforms to ensure they remain effective. You use transforms to make it easy for people to read the notifications. What may be obvious to you may not be clear to the target audience.
Conclusion
EventBridge transforms are a simple yet powerful way to make AWS notifications more user-friendly. Whether sending events to a ticketing system or a chat app, formatting alerts into a clear and concise format can greatly enhance usability and response times.
If you haven’t yet explored EventBridge transforms, I highly recommend giving them a try. Your help desk team (and your future self) will thank you!
Next Steps
Try setting up an EventBridge transform in your AWS account.
Experiment with different input templates.
Share your experiences and best practices in the comments!
Do you have questions or feedback? Drop them below or connect with me on LinkedIn!
Top comments (0)