An EventBridge rule must deliver to a target that expects a payload shape different from the raw event. What do a target's Input, InputPath and InputTransformer settings do, and when do you still need a Lambda in between?
answer
- constant, subset, or template
- named variables from JSONPath
- template output need not be JSON
- substitution only — no logic
- branching means two rules, not a cleverer template
basics
~20 sInput sends a fixed constant payload, InputPath sends a JSONPath-selected subset of the event, and InputTransformer binds JSONPath extractions to named variables and substitutes them into a template. All three only reshape what is already in the event; enrichment needs code.
solid answer
~50 sEach target on a rule can reshape what it receives. `Input` replaces the event with a static JSON constant — handy for targets that just need a trigger with fixed parameters. `InputPath` passes a JSONPath-selected subset, e.g. `$.detail`, so the target sees only the payload. `InputTransformer` is the flexible one: `InputPathsMap` binds names to JSONPath expressions, and `InputTemplate` is a template where `<name>` placeholders are substituted. The template can emit JSON for a structured target, or a plain string, which is what makes a readable Slack or SNS message possible with no code. Reserved variables such as `<aws.events.rule-name>` and `<aws.events.event.json>` are available too. What none of them can do is *add* information: there are no conditionals, no arithmetic, no lookups. The moment the target needs a field that is not in the event, you need real code between the rule and the target.
code
bash · 8 linesaws events put-targets --rule order-alerts --event-bus-name orders-bus --targets '[{
"Id": "notify",
"Arn": "arn:aws:sns:eu-west-1:111122223333:order-alerts",
"InputTransformer": {
"InputPathsMap": { "orderId": "$.detail.orderId", "total": "$.detail.total" },
"InputTemplate": "\"Order <orderId> placed for <total>\""
}
}]'go deeper
Know that a target can be given a constant payload, a subset of the event, or a templated payload, so the target does not have to accept the full event envelope.
Explain the InputPathsMap plus InputTemplate mechanism, that the output can be a plain string rather than JSON, and that reserved variables like the rule name are available.
Show where the boundary is: substitution only, no lookups or conditionals, so enrichment means code — and branching means a second rule with a narrower pattern, not a cleverer template.
Judge where mapping logic should live at all. A template is untested configuration; once it encodes business meaning, argue for moving it into code, or for the producer emitting a richer event so consumers stop reshaping it.
## Why transformation exists at all EventBridge delivers the whole event envelope to a target by default. That is often wrong for the target: an SNS topic that fans out to a phone should get a sentence, not a JSON envelope; a Step Functions state machine wants its own input shape; a downstream HTTP endpoint has a fixed contract. The naive fix — put a Lambda in the middle whose whole job is renaming fields — costs money, latency, a cold start, an execution role, and a piece of code somebody has to own. Target input transformation exists to delete that Lambda. ## The three settings, from least to most flexible **`Input`** is a constant. Whatever the event was, the target receives exactly this JSON. It is used when the rule is really a trigger — the fact that *something* happened is the whole signal — and the target needs fixed parameters. **`InputPath`** is a single JSONPath expression selecting part of the event. `"$.detail"` is the common one: strip the envelope, hand the target just the payload. It cannot rename or restructure; it can only pick a subtree. **`InputTransformer`** has two parts: ```json { "InputPathsMap": { "orderId": "$.detail.orderId", "total": "$.detail.total", "account": "$.account" }, "InputTemplate": "{\"id\": <orderId>, \"amount\": <total>, \"acct\": <account>}" } ``` `InputPathsMap` binds variable names to JSONPath extractions from the event; `InputTemplate` is arbitrary text into which `<variable>` placeholders are substituted. Two properties matter in practice. First, the template does not have to be JSON — a bare quoted string produces a plain-text message, which is exactly what you want for a human-readable notification. Second, several reserved variables are available without declaring them, including `<aws.events.rule-arn>`, `<aws.events.rule-name>`, `<aws.events.event.json>` (the whole event as JSON) and `<aws.events.event.ingestion-time>`. Embedding the rule name in an alert is a small thing that pays off during an incident, because the responder immediately knows which rule fired. ## The hard limit: substitution, not computation The transformer is a **string substitution engine**. It has: - no conditionals — you cannot say "if `status` is FAILED then …"; - no arithmetic, no formatting, no date maths; - no iteration over an array; - no access to anything outside the event — no DynamoDB lookup, no API call, no secret. So the decision rule is simple: **if every value the target needs is already somewhere in the event, use a transformer; if the target needs a value that is not in the event, or the shape depends on the content, you need code.** The classic example is an event carrying a `customerId` where the notification must contain the customer's email address. No transformer can fetch that; a Lambda target that reads the record and calls the downstream service is the honest design. A second, subtler reason to reach for code: branching. If half the events should go to one shape and half to another, do not write a clever template — write **two rules** with narrower patterns, each with its own transformer. Rules are cheap and this keeps the branch visible in configuration rather than hidden in a string. ## Where it goes wrong The most common failure is invalid output. The template is not validated against the target's expectations, so a missing brace or an unquoted string produces a payload the target rejects at invocation time — which shows up as `FailedInvocations`, not as a configuration error. Test with a real event before shipping. The second is a JSONPath that does not resolve. If the field is missing from a particular event, the substitution does not produce the value you expected, and events that looked fine in testing break on an edge case. Guard against it upstream by narrowing the rule's pattern with `{"exists": true}` on the field the transformer depends on, so events lacking it never reach this target at all. The third is scope creep: a template that has grown to encode business meaning. At that point the mapping is logic, it deserves tests, and it belongs in code — not in a JSON string in your infrastructure configuration.
- The template must include the customer's email, but the event only carries a customerId. What do you do?Use a Lambda target. The transformer can only substitute values already present in the event, so any lookup is out of reach. The alternative worth considering is fixing it at the source: if consumers repeatedly need the email, the producer should carry it in the event — event-carried state — and you trade a lookup for a slightly fatter payload.
- Half the events need one target payload and half need another. How do you structure that?Two rules, each with a narrower event pattern and its own input transformer, rather than one rule with a clever template. The transformer has no conditionals, and even if it did, expressing a branch in a template string hides it. Two rules make the branch visible in configuration, and rules are cheap.
- How would you include which rule fired inside the message a target receives?Use the reserved variable `<aws.events.rule-name>` (or `<aws.events.rule-arn>`) directly in the InputTemplate — no InputPathsMap entry needed. During an incident that single token saves the responder from grepping every rule on the bus to find which one produced the alert.
saying these in an interview costs you the question
- Expecting an input transformer to call another service for extra data
- Assuming the template output must be valid JSON
- Confusing input transformation with filtering which events match
- Encoding conditional business logic in a template string
- Not testing the produced payload against the target's contract