All posts

Terraform Operations #6 Execution Platforms Compared: Plain CI, HCP Terraform, Atlantis, and Spacelift
4 min read

Terraform Operations #6 Execution Platforms Compared: Plain CI, HCP Terraform, Atlantis, and Spacelift

Using how far a hand-built GitHub Actions workflow carries you — and where it starts to hurt — as the yardstick, we compare the managed HCP Terraform, the self-hosted OSS Atlantis, and the commercial Spacelift family of platforms. We examine what a platform actually adds — policy as code, RBAC, run history visualization — along with pricing structure, and lay out selection criteria by team size.

Terraform Operations #5 Structuring at Scale: Stack Boundaries, Cross-Stack References, and When to Adopt Terragrunt
5 min read

Terraform Operations #5 Structuring at Scale: Stack Boundaries, Cross-Stack References, and When to Adopt Terragrunt

Examining the problems that appear when a single state grows large — slow plans, a wide blast radius, lock contention between teams — and how to split it into stacks along change frequency, lifetime, and owning team. We compare the two ways to pass values between stacks, terraform_remote_state versus SSM parameters, and their difference in coupling, lay out monorepo conventions, and cover how to judge when boilerplate has crossed the threshold that justifies Terragrunt.

Terraform Operations #4 Security and Cost Scanning: PR Guardrails with trivy, checkov, and Infracost
4 min read

Terraform Operations #4 Security and Cost Scanning: PR Guardrails with trivy, checkov, and Infracost

We compare and adopt trivy and checkov, static scanners that catch security misconfigurations before apply, and set a rule for handling false-positive exceptions in code with the reason attached. With Infracost commenting monthly cost changes on every PR, cost review moves to the pre-deploy stage, and default_tags-based cost tracking completes the PR guardrails.

Terraform Operations #3 Code Quality and Testing: tflint, pre-commit, and terraform test
5 min read

Terraform Operations #3 Code Quality and Testing: tflint, pre-commit, and terraform test

On top of fmt and validate, tflint catches provider-knowledge errors — instance types that do not exist, for example — before plan ever runs, and pre-commit hooks automate all of it at commit time. We learn Terraform's built-in test framework, terraform test, through a module-testing example covering tftest files and the run and assert structure, then close with a practical rule for choosing between plan tests and apply tests based on their cost difference.

Terraform Operations #2 Drift and State Surgery: Scheduled Detection, import Blocks, removed Blocks
5 min read

Terraform Operations #2 Drift and State Surgery: Scheduled Detection, import Blocks, removed Blocks

Changes made outside the code need a detection system: a scheduled plan workflow with -detailed-exitcode catches drift within a day. We lay out the decision criteria for the three responses to drift — absorb into code, revert with apply, or hand over with ignore_changes. Then we adopt console-born resources with the import block, generate a code draft with -generate-config-out, and remove resources from state only — without destroying them — using the removed block.

Terraform Operations #1 Team Workflow: plan Review on PRs, apply via GitHub Actions
4 min read

Terraform Operations #1 Team Workflow: plan Review on PRs, apply via GitHub Actions

Local apply concentrates strong credentials on individual laptops and skips review — problems that surface fast on a team. This post builds the standard workflow with GitHub Actions: PRs get the plan output as a comment, and merging to main triggers apply in CI. We wire up OIDC role assumption, automate plan comments on PRs, and use concurrency to prevent simultaneous applies — the first step toward removing human hands from apply.

Terraform in Practice #10 Domain, HTTPS, and Completion: Route 53, ACM Validation, CloudFront and provider alias
6 min read

Terraform in Practice #10 Domain, HTTPS, and Completion: Route 53, ACM Validation, CloudFront and provider alias

Connecting the Route 53 hosted zone as a data source, issuing an ACM certificate through the three-resource DNS validation idiom, and attaching an HTTPS listener with a redirect to the ALB. We cover using a provider alias to work with us-east-1 for the CloudFront certificate, then wire up a CDN serving the locked-down S3 bucket via OAC and the alias records, completing the architecture built across ten parts.

PostgreSQL LISTEN/NOTIFY: How Far It Goes, and When to Move to a Message Queue
4 min read

PostgreSQL LISTEN/NOTIFY: How Far It Goes, and When to Move to a Message Queue

Sorting out the practical range of PostgreSQL's built-in pub/sub. How notifications ship at commit time as part of the transaction, the 8,000-byte payload cap and the send-only-keys principle, the volatility of notifications with no listener, the commit-serialization bottleneck at high publish volume, the resulting standard combination — notifications as the wake-up signal, work in a SKIP LOCKED table queue — and the criteria for moving to a real message queue.

Terraform in Practice #9 Environment Separation: Workspace Limits, Directory Layout, and moved Refactoring
5 min read

Terraform in Practice #9 Environment Separation: Workspace Limits, Directory Layout, and moved Refactoring

Examining where the workspace approach falls short for environment separation, then setting up the standard practical layout that splits code into modules and envs directories. We refactor the code that grew in a single directory into network, compute, and data modules, using moved blocks to relocate addresses without recreating anything, and finish with dev and prod running the same modules with different values.

PostgreSQL Row-Level Security: Making the Database Enforce Multi-Tenant Isolation
4 min read

PostgreSQL Row-Level Security: Making the Database Enforce Multi-Tenant Isolation

A practical introduction to row-level access control (RLS). The structure that stops the worst multi-tenant accident — a missing WHERE tenant_id — with database enforcement instead of application discipline, the basic form of ENABLE ROW LEVEL SECURITY and CREATE POLICY, the standard current_setting pattern for per-request tenant selection and its connection-pool caveat, the performance condition (an index on tenant_id), and the cases where not using RLS is the better call.

Terraform in Practice #8 Deploying on ECS Fargate: Task Definitions, Services, and the Cutover Behind the ALB
5 min read

Terraform in Practice #8 Deploying on ECS Fargate: Task Definitions, Services, and the Cutover Behind the ALB

Examining the limits of the user_data approach and moving the compute layer to containers. We build an ECS cluster and a Fargate task definition, separate the execution role from the task role, create a service with an ip-type target group, and run EC2 and containers side by side behind the same ALB before cutting over with a single listener change — all in code.

Terraform in Practice #7 IAM as Code: Instance Roles, Least Privilege, and GitHub Actions OIDC
5 min read

Terraform in Practice #7 IAM as Code: Instance Roles, Least Privilege, and GitHub Actions OIDC

Writing trust policies and permission policies with the aws_iam_policy_document data source, then attaching a role to EC2 through an instance profile to complete SSM Session Manager access and secret reads. We narrow least privilege down to individual resource ARNs, and build the OIDC federation that lets GitHub Actions assume an AWS role without access keys — all in code.