Subscribing to events on a Custom Event Bus
A subscriber is one resource that says which events you want and where to send them. You create
it with CreateSubscriber, naming the bus, the filters, and one target. It watches
that bus, keeps the events that match its filters, optionally transforms each one, and delivers
it to exactly one target. To fan an event out to several targets, create one subscriber for each
target on the same bus.
EventBridge applies one subscriber create or delete at a time on a given bus, whichever account calls. A
second CreateSubscriber or DeleteSubscriber on the same bus while one is in
progress fails with ConcurrentModificationException; retry it. The create and delete rates
in Custom Event Bus quotas therefore apply per bus.
Filtering which events reach the target
FilterConfiguration holds a list of Filters. Each filter has a
Pattern, in EventBridge event pattern syntax, and one Scope. You can have at
most one filter per scope, and EventBridge delivers an event only if it matches every filter in the
list. A subscriber without a FilterConfiguration receives every event on the
bus.
-
DATA: matches the payload. Write the pattern against the shape described in Event structure: data, metadata, and system metadata. -
METADATA: matches the key-value pairs a producer set withPutRawEvents, exact match only. -
SYSTEM_METADATA: matches the fields EventBridge sets, such asaws:SourceorEventGroupId.
For the pattern syntax, the scope rules, and examples, see Filtering events for a subscriber.
Transforming the payload
Transformer.Type selects what the target receives. A universal target does not use it;
see Universal targets for a Custom Event Bus.
-
RAW, the default. The payload alone. -
WITH_METADATA. The full event:Data,Metadata, andSystemMetadata. -
JSONATA. The result of the JSONata expression inJsonataConfiguration.Expression, wrapped in{% %}delimiters, with the event available as$events.
EventBridge checks the syntax of an expression when you create the subscriber and evaluates
it at delivery time. An expression that throws, or that produces no value, fails the
delivery of that event. Test expressions against real events before you depend on
them. For what $events holds, the extra functions, and the limits, see
Transforming events with JSONata.
Delivering to one target
InvokeConfiguration carries the TargetArn, the
RoleArn that EventBridge assumes to invoke the target, and at most one parameter
block that matches the target type. Most parameter values accept a JSONata expression, so a
value can come from the event. The following table lists the bespoke target types and their
parameter block; each has its own page under Targets for a Custom Event Bus subscriber.
| Target | Parameter block |
|---|---|
| Amazon SQS queue | SqsParameters |
| Lambda function | LambdaParameters |
| Kinesis stream | KinesisParameters |
| Step Functions state machine | StepFunctionsParameters |
| Amazon SNS topic | SnsParameters |
| HTTP endpoint or API destination | HttpParameters |
| Firehose stream | FirehoseParameters |
An Custom Event Bus or a Custom Event Bus - Classic can also be the target: set the bus ARN as
TargetArn. For a FIFO target such as an Amazon SQS FIFO queue, set the target's own
deduplication identifier in the parameter block, for example
SqsParameters.MessageDeduplicationId, to a per-message value derived from the event
with a JSONata expression. A constant makes the target discard every message after the first.
A universal target invokes an Amazon API action directly, with no
function in between. Its ARN has the form
arn:aws:events:::aws-sdk:,
for example service:apiActionarn:aws:events:::aws-sdk:dynamodb:putItem, and its
UniversalTargetParameters.Input holds the request as JSON or as a JSONata
expression that produces it. For the naming rules, batching, and failure behavior, see
Universal targets for a Custom Event Bus.
When you create the subscriber, EventBridge resolves the target type from the ARN and checks three things: that the parameter block matches the target type, that the ARN belongs to your account, and that every expression parses. Whether the target exists, whether the role can reach it, and whether the target's API accepts the values are checked at delivery, so confirm the first delivery at the target.
Retries and dead-letter queues
RetryPolicy sets how long EventBridge retries a failed delivery, by default 5 attempts within 300
seconds, and OnFailureConfiguration.Arn names the Amazon SQS queue that receives a record for each
event that exhausted its retries. Set both when you create the subscriber. For the limits, the record
format, and how to redrive, see Retry policies and dead-letter queues.
The delivery role
The role in RoleArn must belong to your account and trust the
events.amazonaws.com service principal. Your caller needs iam:PassRole
on the role to create the subscriber, or EventBridge denies the request before it checks the target
ARN. The role's permissions policy needs two grants.
-
The action the target requires, for example
sqs:SendMessageon a queue,lambda:InvokeFunctionon a function,sns:Publishon a topic, orkinesis:PutRecordson a stream. -
sqs:SendMessageon the dead-letter queue inOnFailureConfiguration.Arn. Without it, a failed delivery has nowhere to record itself, and those events are lost with no signal.
The following trust policy allows EventBridge to assume the role.
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "events.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
The following permissions policy delivers to an Amazon SQS queue and dead-letters to a second queue.
{ "Version": "2012-10-17", "Statement": [ { "Sid": "InvokeTheTarget", "Effect": "Allow", "Action": "sqs:SendMessage", "Resource": "arn:aws:sqs:us-east-1:111122223333:large-orders" }, { "Sid": "WriteToTheDeadLetterQueue", "Effect": "Allow", "Action": "sqs:SendMessage", "Resource": "arn:aws:sqs:us-east-1:111122223333:large-orders-dlq" } ] }
Example: deliver large orders to a queue
The following command creates a subscriber that delivers orders over 500 to an Amazon SQS
queue, for events published with PutEvents, and sends failures to a
dead-letter queue.
aws eventsv2 create-subscriber \ --name large-orders \ --event-bus-arn arn:aws:events:us-east-1:111122223333:event-busv2/orders/EXAMPLE1234567890abcdef \ --filter-configuration '{ "Filters": [ { "Scope": "DATA", "Pattern": "{\"detail\":{\"total\":[{\"numeric\":[\">\",500]}]}}" } ] }' \ --invoke-configuration '{ "TargetArn": "arn:aws:sqs:us-east-1:111122223333:large-orders", "RoleArn": "arn:aws:iam::111122223333:role/EventBusDeliveryRole" }' \ --on-failure-configuration '{ "Arn": "arn:aws:sqs:us-east-1:111122223333:large-orders-dlq" }'
Troubleshooting: you published and nothing arrived at the target
A publish response says only that the bus accepted and stored the event; it never confirms delivery. Work through the following checks in order.
- Symptom
The publish call returned HTTP 200 with no failed entries, and the target has received nothing after several minutes.
- Cause
One of five things, in order of frequency: delivery is still being retried; the subscriber is
STOPPEDor revoked; the subscriber'sStartingPositionisLATESTand the event was published before the subscriber existed; the filter is written for the other publish API and matches nothing; or the delivery role cannot reach the target or the dead-letter queue.TargetInvocationstells you which half of the problem you have. Datapoints onTargetInvocationswith none onEventsDeliveredmean that deliveries are attempted and fail. No datapoints onTargetInvocationswhileFilterEvaluatedhas them means that no delivery is attempted; check that the subscriber isRUNNING, and checkEventTransformationFailures.- Solution
-
Read the subscriber.
Statemust beRUNNINGandRevokedmust be absent; it appears only when true. NoteStartingPositionand the filters.aws eventsv2 describe-subscriber \ --subscriber-arn arn:aws:events:us-east-1:111122223333:subscriber/large-orders/EXAMPLE1234567890abcdefRead the subscriber's metrics in
AWS/EventsV2.FilterEvaluatedat zero means no event reached this subscriber: the producer published to another bus, or before the subscriber existed withLATEST.FilterEvaluatedabove zero withFilterMatchedat zero means the filter matched nothing; see Event structure: data, metadata, and system metadata. WhenFilterMatchedhas datapoints andEventsDelivereddoes not, deliveries are failing, and which metric records the outcome depends on the subscriber:EventsDroppedwhen no dead-letter queue is configured,OnFailureDestinationDeliveredwhen the event reached the queue, andOnFailureDestinationFailedwhen it did not.Turn on logs and reproduce. Set
LogConfiguration.LeveltoINFOandIncludePayloadtoFULL, wire a log delivery, publish again, and read theEVENT_DELIVERY_ATTEMPTrecords. Each carries the target's own error code and message, anddetails.target_input, which is what EventBridge sent rather than what you meant to send. See Observability for the Custom Event Bus: metrics, logs, and CloudTrail.If the filter is the suspect, add a diagnostic subscriber on the same bus with no filter,
Transformer.TypeWITH_METADATA, and a queue you own as the target. It delivers each event exactly as EventBridge sees it, asData,Metadata, andSystemMetadata. Then simplify your filter one condition at a time; the last condition you remove is the cause.
- Verification
Publish one event that should match and one that should not. The first arrives at the target and
EventsDeliveredincrements by one; the second does not arrive andFilterEvaluatedincrements whileFilterMatcheddoes not.
Note
A subscriber's metrics are available to the bus owner and to the subscriber's owner; its logs are delivered only to the subscriber's owner.