ADR-051: Infrastructure Simplification - KISS Principle Applied
Status: Accepted Date: 2025-10-24 Deciders: Infrastructure Team, Development Team, Architect Technical Story: Reduce infrastructure complexity by eliminating redundant files and consolidating deployment logic
Context and Problem Statement
Our infrastructure codebase has grown organically over multiple iterations, resulting in:
- Excessive File Count: 58 infrastructure-related files across 4 directories
- Redundant Implementations: Multiple versions of similar functionality (PowerShell + Bash + Bicep)
- Scattered Documentation: Deployment guides in 3+ locations with conflicting information
- Temporary Files Committed: 26 planning documents mixed with production code
- Duplicate Modules: Multiple Bicep modules for similar Azure resources (e.g., Container Apps that are being replaced)
- Complex Maintenance: Any infrastructure change requires updates to 5+ files
Current State Analysis: - Infrastructure files: 58 total - Deployment scripts: 16 (8 Bash + 8 PowerShell) - Bicep modules: 18 - Parameter files: 14 (7 dev + 7 test) - Helper scripts: 5 - Compiled ARM templates: 2 (unnecessary) - Temporary planning docs: 26 (should be in temp/ folder)
Problem Impact: - New developers struggle to find correct deployment documentation - Unclear which scripts/modules are authoritative vs experimental - Difficult to ensure consistency across Bash and PowerShell versions - High maintenance burden (single change affects many files)
Decision Drivers
- KISS Principle: Keep It Simple, Stupid - eliminate unnecessary complexity
- Maintainability: Reduce files that need updating for infrastructure changes
- Developer Experience: Clear, obvious path for deployment and troubleshooting
- Code Quality: Remove dead code, obsolete experiments, and redundant implementations
- Documentation: Single source of truth for deployment procedures
Decision
Aggressively simplify infrastructure codebase by applying KISS principle:
1. Delete Obsolete Container Apps Files (10 files)
Why: Migrating from Container Apps to ACI, these are no longer needed:
# Bicep modules (4 files)
infrastructure/bicep/modules/container-app-api.bicep
infrastructure/bicep/modules/container-app-mcp-server.bicep
infrastructure/bicep/modules/container-app-ui.bicep
infrastructure/bicep/modules/container-platform.bicep
# Deployment scripts (4 files)
infrastructure/scripts/build-and-push-images.sh
infrastructure/scripts/build-images-in-acr.sh
infrastructure/scripts/configure-acr-developer-access.sh
infrastructure/scripts/deploy-all-layers.sh
# Parameter files (2 files)
infrastructure/bicep/environments/dev-layer4.parameters.json
infrastructure/bicep/environments/test-layer4.parameters.json
2. Delete Redundant/Superseded Files (11 files)
Why: Replaced by simpler alternatives or no longer relevant:
# VPN Gateway modules (replaced by Bastion)
infrastructure/bicep/modules/vpn-gateway.bicep
infrastructure/bicep/modules/vpn-gateway-with-azure-ad.bicep
# Private endpoint modules (consolidated into single module)
infrastructure/bicep/modules/acr-private-endpoint.bicep
infrastructure/bicep/modules/ai-foundry-private-endpoints.bicep
# Subnet delegation utility (one-time operation, no longer needed)
infrastructure/bicep/modules/subnet-delegation-update.bicep
# Helper scripts (functionality consolidated)
infrastructure/scripts/helpers/acr-build-helpers.sh
infrastructure/scripts/helpers/docker-compose-helpers.sh
infrastructure/scripts/helpers/image-build-helpers.sh
infrastructure/scripts/helpers/layer-dependency-helpers.sh
infrastructure/scripts/helpers/validation-helpers.sh
# Compiled ARM templates (never use compiled ARM, always use Bicep)
infrastructure/bicep/compiled/full-deployment.json
3. Delete Temporary Planning Documents (26 files)
Why: These should never have been committed, belong in temp/ folder:
# Planning documents (all files starting with TEMP-, PLANNING-, DRAFT-)
infrastructure/temp/TEMP-*
infrastructure/temp/PLANNING-*
docs/temp/DRAFT-*
# (see full list in migration guide documentation audit)
4. Consolidate Deployment Scripts (Prefer Bash)
Decision: Maintain ONLY Bash versions of deployment scripts - PowerShell scripts were created as alternatives, but Bash works cross-platform - Bicep CLI works identically on Windows/Linux/Mac via Bash - Reduce duplication: 16 scripts → 8 scripts (50% reduction)
Keep (Bash):
- deploy-foundation.sh
- deploy-substrate.sh
- deploy-ai-models.sh
- deploy-apps.sh
- install-prerequisites.sh
- teardown.sh
- validate-deployment.sh
- build-and-push-to-acr.sh (new, consolidates image building)
Delete (PowerShell - redundant):
- deploy-foundation.ps1
- deploy-substrate.ps1
- deploy-ai-models.ps1
- deploy-apps.ps1
- install-prerequisites.ps1
- teardown.ps1
- validate-deployment.ps1
Rationale: - PowerShell works on all platforms (pwsh), but adds maintenance burden - Bicep deployment via Azure CLI is identical across platforms - Every script change requires updating 2 files (Bash + PowerShell) - Most cloud engineers are familiar with Bash (Linux heritage) - Azure Cloud Shell uses Bash by default
5. Consolidate Bicep Modules (Keep 10 Core Modules)
After cleanup, keep these essential modules:
infrastructure/bicep/modules/
├── networking.bicep # VNet, Subnets, NSGs
├── bastion-vm.bicep # Bastion + Windows Jump Box (new)
├── managed-identity.bicep # System-assigned identity
├── log-analytics.bicep # Monitoring workspace
├── ai-services.bicep # AI Foundry Hub + Project
├── container-registry.bicep # ACR
├── container-group-aci.bicep # ACI deployment (new)
├── ai-model-deployment.bicep # AI model deployments
├── security.bicep # Key Vault
└── private-endpoints.bicep # Generic PE module
Result: 18 modules → 10 modules (44% reduction)
6. Simplify Parameter Files (8 Files Total)
infrastructure/bicep/environments/
├── dev-foundation.parameters.json # Foundation layer (dev)
├── dev-substrate.parameters.json # Substrate layer (dev)
├── dev-ai-models.parameters.json # AI Models layer (dev)
├── dev-apps.parameters.json # Apps layer (dev)
├── test-foundation.parameters.json # Foundation layer (test)
├── test-substrate.parameters.json # Substrate layer (test)
├── test-ai-models.parameters.json # AI Models layer (test)
└── test-apps.parameters.json # Apps layer (test)
Result: 14 parameter files → 8 parameter files (43% reduction)
7. Consolidate Documentation (5 Essential Docs)
Keep in docs/deployment/:
docs/deployment/
├── README.md # Overview + quick links
├── azure-infrastructure-guide.md # Complete deployment guide
├── bastion-dev-access.md # Dev environment access
├── troubleshooting.md # Common issues + fixes
└── architecture-diagrams.md # Visual reference
Delete/Archive: - Old VPN guides (superseded by Bastion) - Redundant "getting started" docs - Experiment documentation - Conflicting deployment instructions
Consequences
Positive
- Massive Simplification: 58 files → 25 files (57% reduction)
- Easier to understand system
- Faster onboarding for new developers
-
Less maintenance burden
-
Single Source of Truth: Clear, authoritative files for each concern
- One deployment script per layer (Bash only)
- One Bicep module per Azure resource type
-
One documentation guide per topic
-
Reduced Duplication: No more syncing Bash + PowerShell
- 50% reduction in deployment scripts
- Changes need updating in fewer places
-
Less risk of inconsistency
-
Clearer Intent: Removed experiments and dead code
- Obvious which files are production vs experimental
- Temporary files in temp/ folder (git-ignored)
-
No confusion about which version to use
-
Better Organization: Logical structure
- Bicep modules organized by resource type
- Scripts organized by deployment layer
-
Documentation organized by user journey
-
Faster Development: Less time navigating files
- Quick to find correct script/module
- Obvious where to make changes
- Faster to validate changes (fewer files to review)
Negative
- Loss of PowerShell Scripts: Windows-centric teams may prefer PowerShell
- Mitigation: Bash works on Windows via WSL, Git Bash, or PowerShell (via
bashcommand) -
Mitigation: Document Bash installation for Windows developers
-
One-Time Migration Cost: Updating references to deleted files
- Mitigation: Clear migration guide with exact commands
-
Mitigation: Phased approach (test in dev before production)
-
Potential Breaking Changes: If any code references deleted files
- Mitigation: Search codebase for references before deletion
-
Mitigation: Update all documentation in same commit
-
Loss of Historical Context: Deleting old experiments may lose insights
- Mitigation: Git history preserves all deleted files
- Mitigation: Document decisions in ADRs (like this one)
Implementation
Deletion Strategy
Phase 1: Safe Deletions (Low Risk)
# Delete temporary planning documents (never should've been committed)
git rm -r infrastructure/temp/TEMP-*
git rm -r infrastructure/temp/PLANNING-*
git rm -r docs/temp/DRAFT-*
# Delete compiled ARM templates (always use Bicep source)
git rm infrastructure/bicep/compiled/*.json
Phase 2: Container Apps Cleanup (Migrating to ACI)
# Delete Container Apps modules (replaced by ACI)
git rm infrastructure/bicep/modules/container-app-*.bicep
git rm infrastructure/bicep/modules/container-platform.bicep
# Delete Container Apps scripts (replaced by ACI scripts)
git rm infrastructure/scripts/build-and-push-images.sh
git rm infrastructure/scripts/build-images-in-acr.sh
git rm infrastructure/scripts/configure-acr-developer-access.sh
git rm infrastructure/scripts/deploy-all-layers.sh
# Delete Container Apps parameters
git rm infrastructure/bicep/environments/*-layer4.parameters.json
Phase 3: Redundant Files (Consolidating)
# Delete redundant PowerShell scripts (keeping Bash only)
git rm infrastructure/scripts/*.ps1
# Delete obsolete VPN Gateway modules (replaced by Bastion)
git rm infrastructure/bicep/modules/vpn-gateway*.bicep
# Delete redundant private endpoint modules (consolidated)
git rm infrastructure/bicep/modules/acr-private-endpoint.bicep
git rm infrastructure/bicep/modules/ai-foundry-private-endpoints.bicep
# Delete one-time subnet delegation utility
git rm infrastructure/bicep/modules/subnet-delegation-update.bicep
# Delete redundant helper scripts (functionality consolidated)
git rm infrastructure/scripts/helpers/*-helpers.sh
Phase 4: Documentation Cleanup
# Archive old deployment docs
git mv docs/deployment/old-vpn-setup.md docs/archive/vpn-setup.md
git mv docs/deployment/container-apps-guide.md docs/archive/container-apps-guide.md
# Delete redundant getting-started docs (consolidated into main guide)
git rm docs/deployment/quick-start-*.md
Validation After Deletion
Verify no broken references:
# Search for references to deleted files
grep -r "container-app-" --include="*.bicep" --include="*.sh" --include="*.md"
grep -r "vpn-gateway" --include="*.bicep" --include="*.sh" --include="*.md"
grep -r "\.ps1" --include="*.md" --include="*.sh"
# Verify deployment still works
./infrastructure/scripts/deploy-foundation.sh dev ldfdev-rg
Comparison: Before vs After
| Metric | Before | After | Reduction |
|---|---|---|---|
| Total Files | 58 | 25 | 57% ⬇️ |
| Deployment Scripts | 16 (8 Bash + 8 PS) | 8 (Bash only) | 50% ⬇️ |
| Bicep Modules | 18 | 10 | 44% ⬇️ |
| Parameter Files | 14 | 8 | 43% ⬇️ |
| Helper Scripts | 5 | 0 (consolidated) | 100% ⬇️ |
| Temp Files | 26 | 0 (deleted) | 100% ⬇️ |
| Documentation Files | 12 | 5 | 58% ⬇️ |
| Compiled ARM | 2 | 0 (deleted) | 100% ⬇️ |
Maintainability Impact: - Infrastructure change affecting all layers: 20+ files → 10 files (50% reduction) - Deployment script update: 2 files (Bash + PS) → 1 file (Bash only) - Documentation update: 3-5 docs → 1-2 docs (single source of truth)
KISS Principle Applied
KISS = Keep It Simple, Stupid
This ADR applies KISS to infrastructure by:
- Eliminating Duplication: One implementation (Bash), not two (Bash + PowerShell)
- Removing Dead Code: Container Apps modules no longer used
- Consolidating Functionality: Helper scripts merged into main deployment scripts
- Cleaning Up Experiments: Temporary files deleted or moved to temp/ folder
- Single Source of Truth: One deployment guide, not multiple conflicting versions
- Obvious Structure: Clear naming, logical organization, no surprises
Quote from "The Pragmatic Programmer":
"Don't live with broken windows. Fix bad designs, wrong decisions, and poor code when you see them."
This cleanup fixes accumulated "broken windows" in our infrastructure codebase.
Success Criteria
- ✅ File count reduced by >50%
- ✅ No broken references to deleted files
- ✅ Deployment still works end-to-end
- ✅ Documentation clear and up-to-date
- ✅ New developers can find what they need quickly
- ✅ Infrastructure changes require updating fewer files
Related ADRs
- Related: ADR-049 (Container Deployment - ACI vs Container Apps) - drives Container Apps file deletion
- Related: ADR-050 (Bastion Replaces VPN Gateway) - drives VPN file deletion
- Related: ADR-052 (Layer Renaming) - drives parameter file consolidation
References
- KISS Principle (Wikipedia)
- The Pragmatic Programmer - Don't Live with Broken Windows
- Technical Debt and Code Smell
- Azure Bicep Best Practices
Status: Accepted Date Accepted: 2025-10-24 Impact: High (major cleanup of infrastructure codebase)