All posts
CloudWatch Metrics and Alarm Costs: The Next Leak After Logs
Decomposing the CloudWatch bill beyond Logs: custom metrics accruing $0.30 a month each and how dimension combinations explode the count, the rates for alarms, dashboards, and API calls (GetMetricData in particular), how third-party observability tools generate metric API charges, cutting counts with the embedded metric format and dimension design, and the inspection order.
Choosing Where to Analyze Logs on AWS: Logs Insights vs Athena vs OpenSearch
A working standard for where to search and analyze logs: Logs Insights querying what already sits in CloudWatch at $0.005 per GB scanned, Athena asking SQL of logs archived in S3 at $5 per TB with partitioning and compression deciding the bill, OpenSearch and its fixed cost for always-on dashboards and full-text search, and the practical setup that layers all three by query frequency.
Kinesis vs MSK vs SQS: Choosing Between Streams and Queues
A working standard for the three services that receive event data: the model split between queues that delete on consumption and streams that replay, SQS's simplicity at $0.40 per million, Kinesis's provisioned shards and on-demand mode, the Kafka-ecosystem requirements that justify MSK, its two branches of Express brokers and Serverless, and a decision order driven by scale and team capability.
Spot Instances in Practice: What the 90% Discount Requires, and Designing for Interruption
What Spot demands in exchange for up to 90% off with no commitment: how the 2-minute interruption notice and rebalance recommendation actually behave, the line between interruption-tolerant workloads and everything else, how the price-capacity-optimized allocation strategy and instance diversification reduce interruption frequency, where Fargate Spot fits, and completing the three cost axes alongside RIs, Savings Plans, and Graviton.
Terraform Dependency Errors, All Three Kinds: Cycle, depends_on Misuse, known after apply
The three families of problems that come out of Terraform's dependency graph, in one place: breaking the classic Error: Cycle of mutually referencing security groups with separate rule resources and diagnosing with terraform graph, why implicit reference-based dependencies are the default and depends_on belongs only to hidden ones plus the side effects of overuse, and fixing the Invalid count argument that appears when uncomputed values reach count and for_each keys.
When Secrets End Up in tfstate in Plaintext: Rotation First, Then Prevention
Starting from the structural fact that tfstate stores values in plaintext regardless of sensitive markings: judging the exposure scope, why key rotation comes before any state cleanup, purging history when state was committed to git, and prevention — ephemeral resources and write-only arguments that keep values out of state, S3 backend encryption and access control, and designs where Terraform never touches the secret at all.
When terraform plan Is Slow: Refresh Load, Parallelism, and the Stack-Split Signal
Starting from the fact that plan time is dominated not by diff computation but by refresh, which reads the API for every resource: how resource count times API round trips sets the duration, the situations where -refresh=false is legitimate and where it is not, where raising parallelism collides with rate limits, why -target is not a performance tool, and the signals that say the real fix is splitting the stack.
Upgrading to AWS Provider 6.x: Diagnosing Breaking Changes and a Safe Transition Order
A safe procedure for AWS provider major upgrades: why a provider major hits harder than a CLI upgrade, the standard route through the latest 5.x to burn down deprecation warnings, the main 6.0 changes (resource-level region, OpsWorks and SimpleDB removal, strict booleans, flipped Redshift defaults), reading the plan to separate cosmetic schema diffs from real replacements, and the trap of shared modules pinning provider versions.
Upgrading Terraform Safely: Compatibility Promises, No-op Verification, Rollback Prep
A safe procedure for raising the Terraform CLI version: the v1.x compatibility promises that keep configurations working across minors, why CLI and provider upgrades must be separated, verifying with a no-changes plan before and after, the rollback preparation needed because state written by a newer version may be unreadable to older ones, and pinning team and CI versions with tfenv and mise.
When terraform destroy Fails: DependencyViolation and Resources That Won't Delete
The three branches of destroy failure, told apart: the diagnosis path for DependencyViolation caused by resources created outside Terraform still holding on, non-empty S3 buckets and why force_destroy needs an apply before the destroy, the correct release procedure for deliberate safety catches like prevent_destroy and deletion_protection, timeouts on slow-deleting resources, and cleaning up after a partial destroy.
When terraform plan Succeeds but apply Fails: Causes and Partial-Apply Recovery
Why a clean plan can still fail at apply: the asymmetry where plan validates only schema and references while real API validation happens at apply, the five typical causes (missing permissions, IAM propagation delays, service quotas, globally unique name collisions, parameter combinations), the safe recovery procedure for the partial-apply state that a non-transactional apply leaves behind, and when an already-exists error calls for import.
Route 53 Routing Policies Compared: Choosing Among the 8 Policies
A scenario-driven standard for Route 53's eight routing policies: what simple, weighted, latency, failover, geolocation, geoproximity, multivalue, and IP-based are each for, the query rates that vary by policy ($0.40–$0.80 per million) and the effect of free alias queries, health check pricing and pairing rules, and the answers for canary deploys, DR, and multi-region.