Advanced Custom Event Bus Subscriber Configuration

Create three EventBridge custom event bus subscribers, each using more features: filter, then retry and dead-letter queue, then a JSONata transform.

A subscriber on an Amazon EventBridge custom event bus delivers matching events to a target, and can filter, retry, dead-letter, and transform along the way. This snippet creates three subscribers, each using more of those features than the last, so you can see what each one adds.
Subscriber 1 filters only. Subscriber 2 adds a retry policy and a dead-letter queue for delivery resilience. Subscriber 3 adds a JSONata transform that reshapes the payload before delivery.
The three subscribers use different comparison operators in their filters, and a final block lists more reusable filter values you can swap in. The target, delivery role, and dead-letter queue must belong to the account creating the subscriber.

Select language:

AWS CLI

Replace the placeholders with your own ARNs. The most basic subscriber: a DATA-scoped filter that delivers only events whose detail.status equals PLACED, and drops everything else.

BUS_ARN="<EVENT_BUS_ARN>"
QUEUE_ARN="<TARGET_QUEUE_ARN>"
ROLE_ARN="<DELIVERY_ROLE_ARN>"

aws eventsv2 create-subscriber \
  --name "orders-basic" \
  --event-bus-arn "$BUS_ARN" \
  --filter-configuration "$(cat <<EOF
{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"status\":[\"PLACED\"]}}"}]}
EOF
)" \
  --invoke-configuration "$(cat <<EOF
{"TargetArn":"$QUEUE_ARN","RoleArn":"$ROLE_ARN"}
EOF
)"

                                                      



Select language:

AWS CLI

A more resilient subscriber. Adds --retry-policy to retry failed deliveries and --on-failure-configuration to send events that exhaust their retries to an SQS dead-letter queue. Uses a numeric-range filter.

BUS_ARN="<EVENT_BUS_ARN>"
QUEUE_ARN="<TARGET_QUEUE_ARN>"
ROLE_ARN="<DELIVERY_ROLE_ARN>"
DLQ_ARN="<DEAD_LETTER_QUEUE_ARN>"

aws eventsv2 create-subscriber \
  --name "orders-resilient" \
  --event-bus-arn "$BUS_ARN" \
  --filter-configuration "$(cat <<EOF
{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"total\":[{\"numeric\":[\">\",100,\"<=\",500]}]}}"}]}
EOF
)" \
  --invoke-configuration "$(cat <<EOF
{"TargetArn":"$QUEUE_ARN","RoleArn":"$ROLE_ARN"}
EOF
)" \
  --retry-policy "$(cat <<EOF
{"MaxRetryAttempts":10,"MaxEventAgeInSeconds":3600}
EOF
)" \
  --on-failure-configuration "$(cat <<EOF
{"Arn":"$DLQ_ARN"}
EOF
)"

                                                      



Select language:

AWS CLI

The fully featured subscriber. Adds --transformer with Type JSONATA to reshape the payload before delivery, on top of the filter, retry, and dead-letter queue. Uses an $or filter across fields.

BUS_ARN="<EVENT_BUS_ARN>"
QUEUE_ARN="<TARGET_QUEUE_ARN>"
ROLE_ARN="<DELIVERY_ROLE_ARN>"
DLQ_ARN="<DEAD_LETTER_QUEUE_ARN>"

aws eventsv2 create-subscriber \
  --name "orders-full" \
  --event-bus-arn "$BUS_ARN" \
  --filter-configuration "$(cat <<EOF
{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"\$or\":[{\"priority\":[\"HIGH\"]},{\"total\":[{\"numeric\":[\">=\",1000]}]}]}}"}]}
EOF
)" \
  --invoke-configuration "$(cat <<EOF
{"TargetArn":"$QUEUE_ARN","RoleArn":"$ROLE_ARN"}
EOF
)" \
  --retry-policy "$(cat <<EOF
{"MaxRetryAttempts":10,"MaxEventAgeInSeconds":3600}
EOF
)" \
  --on-failure-configuration "$(cat <<EOF
{"Arn":"$DLQ_ARN"}
EOF
)" \
  --transformer "$(cat <<EOF
{"Type":"JSONATA","JsonataConfiguration":{"Expression":"{% { \"orderId\": \$events.Data.detail.orderId, \"total\": \$events.Data.detail.total } %}"}}
EOF
)"

                                                      



Filtering with comparison operators

Five DATA-scoped filter values using EventBridge comparison operators: numeric range, anything-but, begins-with (prefix), exists, and $or across fields. Swap any one into the --filter-configuration of a subscriber above.

# Numeric (range): total > 100 and <= 500.
FILTER='{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"total\":[{\"numeric\":[\">\",100,\"<=\",500]}]}}"}]}'

# Anything-but: status is any value except "CANCELLED".
FILTER='{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"status\":[{\"anything-but\":\"CANCELLED\"}]}}"}]}'

# Begins with (prefix): region starts with "us-".
FILTER='{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"region\":[{\"prefix\":\"us-\"}]}}"}]}'

# Exists: the couponCode field is present.
FILTER='{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"couponCode\":[{\"exists\":true}]}}"}]}'

# Or across fields ($or): priority is "HIGH" OR total is >= 1000.
FILTER='{"Filters":[{"Scope":"DATA","Pattern":"{\"detail\":{\"$or\":[{\"priority\":[\"HIGH\"]},{\"total\":[{\"numeric\":[\">=\",1000]}]}]}}"}]}'

                                


Created by:

Marco Buss

Marco Buss

Sr. Solutions Architect at AWS

Follow on LinkedIn