Rejecting DevOps Frameworks: Why We Ditched Complex Toolchains for Terraform Principles
\n\nWhat Was Done
\n\nIn early July 2026, Dablio's engineering board evaluated a comprehensive DevOps toolchain proposal designed to standardize CI/CD pipelines across our infrastructure estate. After deliberation, the board rejected the full-framework approach and instead adopted a minimal Terraform-based infrastructure-as-code pattern tailored to our actual deployment topology.
\n\nThis decision reflected a hard-won principle: complexity should never exceed the problem it solves. Our infrastructure—approximately 15 static S3+CloudFront sites, verified shell deploys, single-file Lambda functions, launchd/cron jobs, and nightly deterministic tests—doesn't require enterprise toolchain scaffolding.
\n\nThe Problem We Solved
\n\nOur deployment footprint spans multiple deployment methods:
\n\n- \n
- Static websites hosted on S3 with CloudFront distributions (CDN cache invalidation required) \n
- Single-file Lambda functions deployed via AWS API or shell scripts \n
- Periodic tasks managed by launchd on macOS and traditional cron on Linux \n
- Git-mirrored repositories for disaster recovery and audit trails \n
- Nightly deterministic integration tests that verify end-to-end functionality \n
A traditional CI/CD framework (Jenkins, GitLab Runner, or similar) would add operational burden: container orchestration, secrets management, pipeline state, job scheduling complexity, and vendor lock-in. For our scale, this was organizational overhead.
\n\nTechnical Architecture: The Terraform-Centric Approach
\n\nInstead, we adopted a Terraform-primary deployment model with the following structure:
\n\nState Management
\n\nTerraform state files are stored in S3 with versioning enabled (bucket: dablio-terraform-state-prod) and DynamoDB-based state locking (table: terraform-locks). This ensures atomic operations and prevents concurrent apply races.
terraform {\n backend \"s3\" {\n bucket = \"dablio-terraform-state-prod\"\n key = \"prod/terraform.tfstate\"\n region = \"us-east-1\"\n encrypt = true\n dynamodb_table = \"terraform-locks\"\n }\n}\n\n\nStatic Site Deployment
\n\nFor S3+CloudFront sites (e.g., s3://sailjada-public, s3://dablio-knowledge-base), we use Terraform to:
- \n
- Define S3 bucket policies and lifecycle rules \n
- Manage CloudFront distributions with origin configurations \n
- Automate cache invalidation via
aws_cloudfront_invalidationresources \n - Route traffic through Route53 alias records \n
Deployment flow: Git commit → shell script calls terraform plan → optional manual review → terraform apply → S3 sync via AWS SDK → CloudFront cache purge.
Lambda Deployment
\n\nSingle-file Lambda functions (e.g., src/lambdas/daily_report_generator.py, src/lambdas/webhook_handler.js) are packaged and versioned using Terraform's aws_lambda_function resource with filename or s3_key parameters. IAM roles and environment variables are defined in Terraform alongside the function code.
Example structure:
\n\nresource \"aws_lambda_function\" \"daily_report\" {\n filename = \"./dist/daily_report_generator.zip\"\n function_name = \"dablio-daily-report\"\n role = aws_iam_role.lambda_exec.arn\n handler = \"index.handler\"\n runtime = \"python3.11\"\n timeout = 60\n\n environment {\n variables = {\n DB_HOST = var.db_host\n LOG_LEVEL = \"INFO\"\n }\n }\n}\n\n\nScheduled Tasks
\n\nFor launchd-managed tasks on macOS and cron on Linux, we define shell scripts in /opt/dablio/scripts/ and configure them via Terraform-generated systemd units or plist files. This ensures version control and auditability:
resource \"local_file\" \"daily_sync_plist\" {\n filename = \"/Library/LaunchDaemons/com.dablio.sync.plist\"\n content = templatefile(\"${path.module}/launchd.plist.tpl\", {\n script_path = \"/opt/dablio/scripts/git_mirror_sync.sh\"\n interval = 3600\n })\n}\n\n\nKey Decision: Why Reject the Framework?
\n\nThe board's reasoning centered on three factors:
\n\n- \n
- Deployment Topology Mismatch: Most CI/CD frameworks assume containerized, stateless workloads. Our S3 sites, Lambdas, and scheduled tasks don't require orchestration—they require configuration management. \n
- Operational Simplicity: Terraform is declarative, version-controlled, and auditable. Adding Jenkins/GitLab runners introduces another system to monitor, patch, and secure. Shell scripts + Terraform cover our actual needs. \n
- Cost: Running a CI/CD cluster (even minimal) costs $50–200/month. Our current approach (Terraform state in S3, cron jobs on existing infrastructure) costs ~$5/month. \n
This reflects Dablio's design principle: adopt infrastructure patterns that match the problem scale, not abstract best practices.
\n\nPending Questions: DBG Mobile App
\n\nThe board identified that Dablio Bank & Green (DBG) may require mobile app deployment in the coming weeks. This changes the calculus: mobile app CI/CD (code signing, test automation, app store submission) may justify adopting GitHub Actions or a lightweight custom pipeline.
\n\nTickets opened for investigation:
\n\n- \n
- DBG AWS config dump and environment variable audit (ticket: DBG-CONFIG-AUDIT) \n
- DBG licensure pre-check workflow (ticket: DBG-LICENSURE-CHECK) \n
- Mobile app demand-test path validation (ticket: DBG-DEMAND-TEST) \n
These will inform whether we extend the Terraform approach or introduce a targeted CI/CD pipeline.
\n\nWhat's Next
\n\nImmediate next steps:
\n\n- \n
- Migrate all static site deployments to Terraform-managed CloudFront invalidations (currently manual) \n
- Audit all existing Lambda IAM roles and consolidate via Terraform modules \n
- Implement nightly deterministic tests as Lambda-scheduled tasks with Terraform-defined CloudWatch alarms \n
- Complete DBG requirements assessment by end of July 2026 \n
This approach buys us flexibility: if DBG adoption accelerates, we can layer GitHub Actions on top of the same Terraform infrastructure without rearchitecting.
"}} ]