12. Operations and the ecosystem
DynamoDB · 12. Operations and the ecosystemThere are no servers to patch, no replicas to promote and no vacuum to schedule. What replaces all of that is access control, client configuration and the tooling around the table — which is where DynamoDB operations actually live.
IAM is the only door
Section titled “IAM is the only door”{ "Effect": "Allow", "Action": ["dynamodb:GetItem", "dynamodb:Query", "dynamodb:PutItem", "dynamodb:UpdateItem"], "Resource": [ "arn:aws:dynamodb:eu-west-1:123456789012:table/AppData", "arn:aws:dynamodb:eu-west-1:123456789012:table/AppData/index/*" ]} NOTE THE SECOND ARN. Index access is a SEPARATE resource. A policy that grants Query on the table but not on /index/* fails at runtime with AccessDeniedException — and it is the single most common IAM mistake with this service.Fine-grained access control
Section titled “Fine-grained access control”IAM conditions can restrict a caller to their own items, enforced by the service rather than by your code:
{ "Effect": "Allow", "Action": ["dynamodb:GetItem", "dynamodb:Query"], "Resource": "arn:aws:dynamodb:eu-west-1:…:table/AppData", "Condition": { "ForAllValues:StringEquals": { "dynamodb:LeadingKeys": ["USER#${cognito-identity.amazonaws.com:sub}"], "dynamodb:Attributes": ["PK", "SK", "name", "email"] } }} dynamodb:LeadingKeys restricts which PARTITION KEYS this principal may touch dynamodb:Attributes restricts which attributes may be read or written dynamodb:Select forbid SELECT ALL, forcing projectionsThis is how mobile and browser clients can talk to DynamoDB directly without a backend — and it only works if your partition keys were designed around identity, which is one more argument for chapter 8’s method.
Encryption and network
Section titled “Encryption and network” AT REST always on. choose the key: AWS owned (default, free) AWS managed (aws/dynamodb) CUSTOMER MANAGED (your KMS key — auditable, revocable, and the one compliance teams ask for)
IN TRANSIT TLS, always.
NETWORK a VPC GATEWAY ENDPOINT keeps traffic off the public internet and removes NAT gateway data charges — which is occasionally a larger line item than the database itself.DAX, when reads are hot and repetitive
Section titled “DAX, when reads are hot and repetitive” DynamoDB Accelerator (DAX) • a write-through cache in front of the table • microsecond reads instead of milliseconds • API-compatible: swap the client, keep the code • an actual CLUSTER of nodes you pay for by the hour — it is not serverless USE IT WHEN DO NOT USE IT WHEN the same items are read every read is unique repeatedly, hot (cache hit rate ≈ 0)
reads vastly outnumber writes dominate writes
sub-millisecond matters 5–10 ms is fine — which is usually trueBefore reaching for DAX, check whether eventually consistent reads (half price, chapter 6) or an application-level cache in something you already run — Redis, or a process-local LRU — solves the same problem for less.
Local development
Section titled “Local development”docker run -p 8000:8000 amazon/dynamodb-localaws dynamodb list-tables --endpoint-url http://localhost:8000 DYNAMODB LOCAL IS ✓ API-compatible: create tables, run queries, test your access patterns ✓ ideal for unit and integration tests
DYNAMODB LOCAL IS NOT ✗ a performance simulator ✗ a capacity simulator — it does not throttle the way the service does ✗ identical in every edge case, especially around limits and index behaviourTreat it as a correctness harness. Load tests belong against a real table, in a real region.
NoSQL Workbench is the other tool worth knowing: it models single-table designs visually, generates sample data, and produces the key structures from chapter 8 without the usual spreadsheet.
Infrastructure as code
Section titled “Infrastructure as code”resource "aws_dynamodb_table" "app" { name = "AppData" billing_mode = "PAY_PER_REQUEST" hash_key = "PK" range_key = "SK"
attribute { name = "PK" type = "S" } attribute { name = "SK" type = "S" } attribute { name = "GSI1PK" type = "S" } attribute { name = "GSI1SK" type = "S" }
global_secondary_index { name = "GSI1" hash_key = "GSI1PK" range_key = "GSI1SK" projection_type = "ALL" }
ttl { attribute_name = "expiresAt" enabled = true } point_in_time_recovery { enabled = true } stream_enabled = true stream_view_type = "NEW_AND_OLD_IMAGES" deletion_protection_enabled = true}That resource carries most of this guide’s operational advice in one place — PITR on, deletion protection on, TTL configured, streams enabled. The Terraform guide covers the surrounding practice; CDK and CloudFormation express the same thing.
Monitoring
Section titled “Monitoring” WATCH, PER TABLE AND PER INDEX ConsumedRead/WriteCapacityUnits ThrottledRequests, Read/WriteThrottleEvents SuccessfulRequestLatency (p50, p99, by operation) SystemErrors, UserErrors ConditionalCheckFailedRequests ReturnedItemCount vs ScannedCount ◄ efficiency
CONTRIBUTOR INSIGHTS names the most-accessed and most-throttled KEYS. the fastest path from "we are throttled" to "this key is why". (ch 3, 13) ScannedCount ≫ ReturnedItemCount means you are reading and paying for data you then discard — a filter doing an index's job. (ch 4)Testing against a real table
Section titled “Testing against a real table” UNIT TESTS DynamoDB Local, or a mocking library. fast, and they prove your key logic.
INTEGRATION TESTS a real table in a test account, created and destroyed per run. on-demand billing makes this nearly free.
LOAD TESTS a real table, provisioned or on-demand, with traffic RAMPED — a cold table splits as it learns your pattern, so the first 90 seconds are not representative (ch 14) WHAT TO ASSERT IN INTEGRATION TESTS • every access pattern from the design document (ch 8) returns what it should • pagination works past one page — insert enough items to cross 1 MB, or force a small Limit • conditional writes fail as expected • consumed capacity is within the expected range — a regression here is a cost regressionThat last assertion is unusual and worth adopting: capturing ConsumedCapacity in tests catches the day someone adds a filter where an index belonged.
Multi-account and tagging
Section titled “Multi-account and tagging” COST ALLOCATION tag every table with a team/service/environment tag, activate the tags in Billing, and the DynamoDB line item becomes attributable rather than a single large number.
ACCOUNT SEPARATION production and non-production in separate AWS accounts is the simplest guarantee that a test cannot scan a production table.
SERVICE LIMITS tables per account, concurrent control-plane operations, and on-demand throughput defaults are all per-account quotas — raise them BEFORE a launch, not during it.The SDK settings that matter
Section titled “The SDK settings that matter”config = Config( retries={"max_attempts": 5, "mode": "adaptive"}, connect_timeout=1, read_timeout=2, max_pool_connections=50,)ddb = boto3.resource("dynamodb", config=config) # created ONCE • adaptive retry mode backs off on throttling instead of amplifying it • short timeouts: a DynamoDB call that takes two seconds is not going to succeed • create the client ONCE, outside the handler (ch 5) • ReturnConsumedCapacity in dev and load testsWhat to take from this chapter
Section titled “What to take from this chapter”- IAM is the only access control, and indexes are a separate resource ARN — forgetting
/index/*is the classic permission bug. - Fine-grained conditions (
dynamodb:LeadingKeys,dynamodb:Attributes) restrict a principal to its own items and attributes, which is what makes direct client access possible — if keys were designed around identity. - Encryption at rest is always on; choose a customer-managed KMS key when auditability matters. A VPC gateway endpoint keeps traffic private and removes NAT charges.
- DAX is a write-through cache cluster for hot, repetitive reads; check eventually consistent reads and an existing cache first.
- DynamoDB Local is a correctness harness, not a performance or capacity simulator. NoSQL Workbench helps design single-table models.
- Express tables in infrastructure as code with PITR, deletion protection, TTL and streams configured — and read the plan before changing a GSI, which can mean delete-and-recreate.
- Monitor per table and per index, and use Contributor Insights to name hot keys.
ScannedCount≫ReturnedItemCountmeans a filter is doing an index’s job. - Configure the SDK: adaptive retries, short timeouts, one client instance, and
ReturnConsumedCapacitywhile developing.
Next: tuning and operations — the levers that actually change latency and cost, and the checklist to run before you ship.