Event-Driven AWS via SDK Best Practices
These are the defaults every EventBridge and Step Functions integration should set explicitly, not leave to chance.
Search across all documentation pages
These are the defaults every EventBridge and Step Functions integration should set explicitly, not leave to chance.
Walk the list once now, then use it as a review checklist before shipping code that publishes events, wires rules and targets, or defines and runs a state machine via SDK.
version or similarly named field in detail so consumers can tell old and new shapes apart as producers evolve.Source. Conventions like orders.api make rules and audits easy to read; avoid free-form or changing source strings.detail additive, not breaking. Add new fields rather than renaming or removing existing ones, so older rules and consumers keep working.Detail deliberately. It is a JSON string, not an object - build it with your language's JSON encoder, never hand-built strings.FailedEntryCount on every PutEvents call. A partial failure across a batch of entries does not raise an exception on its own.TestEventPattern against a real sample event - a silent pattern mismatch means a rule never fires, with no error raised.RoleArn only where the target type requires it. Step Functions and Kinesis targets need an assumable role; scope it to exactly that target.DeleteRule fails while targets remain attached - clean them up in order.Test a pattern before trusting it in production.
# --- Python (boto3) ---
import boto3
import json
events = boto3.client("events")
result = events.test_event_pattern(
EventPattern=json.dumps({"source": ["orders.api"], "detail-type": ["OrderPlaced"]}),
Event=json.dumps({
"source": "orders.api", "detail-type": "OrderPlaced",
"detail": {"orderId": "ord-1"}, "account": "111122223333",
"region": "us-east-1", "time": "2026-07-24T00:00:00Z",
"id": "abc", "resources": [],
}),
)
print(result["Result"]) # True or False// --- TypeScript (AWS SDK v3) ---
import { EventBridgeClient, TestEventPatternCommand } from "@aws-sdk/client-eventbridge";
const events = new EventBridgeClient({});
const result = await events.send(new TestEventPatternCommand({
EventPattern: JSON.stringify({ source: ["orders.api"], "detail-type": ["OrderPlaced"] }),
Event: JSON.stringify({
source: "orders.api", "detail-type": "OrderPlaced",
detail: { orderId: "ord-1" }, account: "111122223333",
region: "us-east-1", time: "2026-07-24T00:00:00Z",
id: "abc", resources: [],
}),
}));
console.log(result.Result); // true or falsePutPermission on the destination bus must exist first, or routed events are rejected.aws:PrincipalOrgID over listing accounts. Authorize a whole organization once instead of maintaining a per-account principal list.DescribeEventBus policies periodically. Remove stale PutPermission statements for accounts or workloads that no longer need access.Ids make multi-account/region fan-out easier to review later.type later. It is fixed at creation - pick correctly up front rather than migrating a live state machine's callers.StartSyncExecution only for Express. It is rejected on Standard machines; poll DescribeExecution there instead.Retry/Catch entries specific-to-general. The first matching ErrorEquals wins, so a States.ALL listed early shadows more specific handling after it.JitterStrategy: "FULL" so many failing executions don't retry on a synchronized schedule.ResultPath on a catcher so the caught error is merged in, not overwriting the state's prior input.States.Permissions failures need an IAM fix, not a Retry block.MaxAttempts deliberately. Standard workflows bill per state transition, so unbounded retries have a direct cost.PutTargets should not carry unrelated permissions.detail or state input. Both can surface in logs and execution history - pass references instead.GetExecutionHistory gives a full state-by-state trace for long-running, exactly-once processes.FailedEntryCount and execution status explicitly. Neither PutEvents nor StartExecution raises on a partial or eventual failure - you must inspect the result.FAILED/TIMED_OUT executions. Route Step Functions execution-status events through EventBridge to a notification target instead of relying on manual checks.Test event patterns with TestEventPattern before relying on them. A pattern typo produces no error - the rule simply never fires, and that failure mode is easy to miss without an explicit test.
Choose Standard vs Express deliberately, based on duration and exactly-once needs, since the type cannot be changed after creation without recreating the state machine.
Grant PutPermission on the destination bus first, prefer aws:PrincipalOrgID over per-account principals, and periodically audit DescribeEventBus policies for stale grants.
List specific ErrorEquals values before States.ALL, since the first matching entry wins and a catch-all listed early shadows more specific handling.
Enable CloudWatch Logs logging on the state machine ahead of time. Express has no console execution history like Standard does, so logging is the only retrospective option.
No. For fast-moving, recently launched services, verify the current supported-integration list in AWS's own documentation rather than assuming a specific action is available.
Scoping execution and invoke roles to exact API actions and target ARNs, rather than granting broad service-level permissions "to make it work."
Route Step Functions execution-status change events through EventBridge to a notification target (SNS, a Lambda, another workflow) instead of manually polling DescribeExecution.
Bound MaxAttempts on retries deliberately and watch for unexpectedly wide fan-out (Parallel/Map states), since Standard bills per state transition.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Reviewed by Chris St. John·Last updated Jul 23, 2026