Design Reviews for New AWS Integrations
A design review is the point where a lead catches expensive mistakes before they are written in code.
Busca en todas las páginas de la documentación
A design review is the point where a lead catches expensive mistakes before they are written in code.
The review is not about code style. It is about four questions that are cheap to answer before an integration ships and expensive to answer after: what can this touch, what does it cost, what happens on retry, and how do we turn it off.
This page gives the checklist to run through, in order, before a service starts calling a new AWS API.
Before approving a new AWS integration, walk least-privilege IAM scope, the cost model, retry/idempotency behavior, and a rollback plan - in that order.
The review does not need a meeting for every integration. A low-risk, read-only call against a service the team already uses can be a five-minute checklist run solo. A new service, a new data store, or anything that writes or spends real money deserves the full conversation, ideally with the review written down somewhere the team can find later.
Run this checklist:
A concrete pass through the checklist for a hypothetical integration: a service starts writing usage events to DynamoDB and occasionally calling Bedrock to summarize them.
IAM scope - the code calls PutItem and Query on one table, and InvokeModel on one specific model ID. The policy should list exactly those three actions, scoped to that table's ARN and that model's ARN - not dynamodb:* or bedrock:*.
Cost model - DynamoDB is billed per request (or per provisioned capacity unit); Bedrock's InvokeModel is billed per input and output token for the specific model. At expected volume, that is estimated up front, not discovered later.
Retry and idempotency - the PutItem call is made idempotent with a conditional expression so a retried write does not double-count a usage event:
# --- Python (boto3) ---
import boto3
from botocore.exceptions import ClientError
ddb = boto3.client("dynamodb", region_name="us-east-1")
try:
ddb.put_item(
TableName="UsageEvents",
Item={"event_id": {"S": event_id}, "count": {"N": "1"}},
# A retried PutItem with the same event_id is a no-op, not a duplicate.
ConditionExpression="attribute_not_exists(event_id)",
)
except ClientError as err:
if err.response["Error"]["Code"] != "ConditionalCheckFailedException":
raise # a real error, not just "already recorded"// --- TypeScript (AWS SDK v3) ---
import { DynamoDBClient, PutItemCommand, ConditionalCheckFailedException } from "@aws-sdk/client-dynamodb";
const ddb = new DynamoDBClient({ region: "us-east-1" });
try {
await ddb.send(new PutItemCommand({
TableName: "UsageEvents",
Item: { event_id: { S: eventId }, count: { N: "1" } },
// A retried PutItem with the same eventId is a no-op, not a duplicate.
ConditionExpression: "attribute_not_exists(event_id)",
}));
} catch (err) {
if (!(err instanceof ConditionalCheckFailedException)) throw err; // a real error
}Rollback plan - the Bedrock summarization call ships behind a feature flag so it can be disabled without a deploy if it starts erroring or costing more than expected, while the underlying PutItem write path (needed regardless) ships unconditionally.
Reviewing permissions before reviewing logic catches the highest-blast-radius mistakes fastest. A policy that is too broad is dangerous even if the code that uses it is perfect today, because it stays broad after the code changes. Reviewing scope first also forces the author to enumerate exactly what their code touches, which is useful information on its own.
"Bedrock is more expensive than a purpose-built service" is true but not actionable. A design review should produce an actual estimate: at N requests per day, with an average input/output token count, the integration costs approximately $X per month. That number is what turns into a real conversation with product about trade-offs - covered in Working with Product on AWS-Cost-Sensitive Features.
Every AWS SDK retries transient failures by default. That means any mutating call in your code can, from the caller's perspective, run more than once for what looks like a single logical action. If the operation is not naturally idempotent (an S3 PutObject to a fixed key is; a "increment a counter" UpdateItem is not), the review needs to identify how duplication is prevented - a conditional expression, a client-supplied idempotency token, or an explicit dedupe check upstream.
The worst time to design a rollback plan is during an incident, under pressure, with the person who understands the integration possibly not on call. Deciding at review time whether a change needs a feature flag - and if so, who owns flipping it - moves that decision out of the stressful moment. See Release Strategy & Feature Flags for AWS-Backed Features for the fuller pattern, including how this composes with Lambda alias-based canary deploys (covered separately in the Lambda section) rather than re-deriving that mechanism here.
| Approach | Use When | Don't Use When |
|---|---|---|
| Full written design review | New service, new data store, anything mutating or cost-sensitive | A single additional read-only call against a service already in use |
| Lightweight solo checklist pass | Low-risk, read-only, or a well-understood pattern the team has used before | The integration is new, unfamiliar, or handles sensitive data |
| Post-hoc audit only | Retrofitting review discipline onto existing, already-shipped integrations | Anything about to ship for the first time - review before, not after |
| Pair programming in place of review | A junior engineer's first mutating call, with a senior engineer present | A stand-in for writing anything down; pairing alone leaves no record |
No. Reserve the full four-part checklist for new services, new mutating operations, or anything touching cost or sensitive data. A single additional read-only call against an already-used service can be a quick solo pass.
IAM scope. A too-broad policy is dangerous on its own, independent of whether the code using it is correct, and it tends to stay broad long after the original code changes.
Identify the service's pricing unit (per-request, per-token, per-GB, or provisioned capacity), then multiply by expected volume and by ten times expected volume, to see how the cost shape scales.
Either the operation is naturally idempotent (like an S3 PutObject to a fixed key), or the code adds an explicit guard - a conditional expression, an idempotency token, or a dedupe check - so a retried call is safe.
Whoever is named in the review as the on-call owner for that integration. Naming a specific person or rotation, not "the team," is what makes the plan usable during an actual incident.
Stack versions: This page was written for boto3 1.43.x (Python 3.10+) and the AWS SDK for JavaScript v3 (Node.js 18+).
Revisado por Chris St. John·Última actualización: 23 jul 2026