Steeds meer SaaS-teams ontdekken dat handmatig servers configureren een bottleneck wordt zodra je groeit. Infrastructure as Code (IaC) lost dit op door je hele infrastructuur — servers, databases, netwerken, DNS — te beschrijven als code die je kunt reviewen, versiebeheren en automatisch uitrollen.
In dit artikel duiken we diep in IaC voor SaaS-producten: waarom je het nodig hebt, welke tools er zijn, en hoe je stap voor stap je eerste IaC-pipeline opzet.
Waarom Infrastructure as Code voor je SaaS?
Het probleem met handmatig beheer
Stel je voor: je SaaS draait op drie servers. Je DevOps-engineer heeft ze maanden geleden ingericht via de AWS-console. Nu moet je een vierde server toevoegen voor een grote klant. Maar niemand weet precies welke instellingen er zijn gebruikt. Klinkt bekend?
Dit is het snowflake server-probleem: elke server is uniek, handmatig geconfigureerd, en onmogelijk exact te reproduceren. Dit leidt tot:
- Configuration drift: servers wijken langzaam af van elkaar
- Geen audit trail: wie heeft wat wanneer gewijzigd?
- Trage disaster recovery: als een server crasht, duurt het uren of dagen om alles opnieuw in te richten
- Onboarding-problemen: nieuwe teamleden snappen de infrastructuur niet
De voordelen van IaC
Met IaC beschrijf je je infrastructuur declaratief:
# Terraform voorbeeld: een PostgreSQL database op AWS RDS
resource "aws_db_instance" "main" {
identifier = "saas-production-db"
engine = "postgres"
engine_version = "16.2"
instance_class = "db.r6g.large"
allocated_storage = 100
max_allocated_storage = 500
storage_encrypted = true
db_name = "saas_production"
username = "app_user"
password = var.db_password
multi_az = true
backup_retention_period = 14
vpc_security_group_ids = [aws_security_group.database.id]
db_subnet_group_name = aws_db_subnet_group.main.name
tags = {
Environment = "production"
ManagedBy = "terraform"
}
}
Dit geeft je:
- Reproduceerbaarheid: exact dezelfde infrastructuur in dev, staging en productie
- Versiebeheer: elke wijziging gaat door een pull request
- Snelle disaster recovery:
terraform applyen je bent weer online - Documentatie: de code ís je documentatie
- Compliance: auditors kunnen precies zien wat er draait en wanneer het is gewijzigd
De grote drie: Terraform, Pulumi en AWS CDK
Terraform (HashiCorp)
Terraform is de industriestandaard. Het gebruikt HCL (HashiCorp Configuration Language), een declaratieve taal die specifiek ontworpen is voor infrastructuur.
Voordelen:
- Enorm ecosysteem met providers voor AWS, GCP, Azure, Cloudflare, Vercel, en honderden andere services
- Mature en stabiel, enorme community
terraform planlaat je precies zien wat er gaat veranderen vóórdat je iets uitvoert
Nadelen:
- HCL heeft beperkingen bij complexe logica (loops, conditionals)
- State management vereist zorgvuldig beheer
- Geen echte programmeertaal — soms frustrerend
# Meerdere omgevingen met Terraform workspaces
variable "environment" {
type = string
}
locals {
instance_sizes = {
development = "db.t3.micro"
staging = "db.t3.small"
production = "db.r6g.large"
}
}
resource "aws_db_instance" "main" {
instance_class = local.instance_sizes[var.environment]
# ... rest van de configuratie
}
Pulumi
Pulumi laat je infrastructuur beschrijven in echte programmeertalen: TypeScript, Python, Go of C#. Voor SaaS-teams die al veel TypeScript schrijven, voelt dit natuurlijk aan.
import * as aws from "@pulumi/aws";
import * as pulumi from "@pulumi/pulumi";
const config = new pulumi.Config();
const environment = pulumi.getStack(); // dev, staging, prod
const instanceSizes: Record<string, string> = {
dev: "db.t3.micro",
staging: "db.t3.small",
prod: "db.r6g.large",
};
const database = new aws.rds.Instance("main-db", {
identifier: \`saas-\${environment}-db\`,
engine: "postgres",
engineVersion: "16.2",
instanceClass: instanceSizes[environment],
allocatedStorage: environment === "prod" ? 100 : 20,
storageEncrypted: true,
multiAz: environment === "prod",
backupRetentionPeriod: environment === "prod" ? 14 : 1,
});
export const dbEndpoint = database.endpoint;
Voordelen:
- Echte programmeertaal met volledige IDE-support
- Makkelijke abstracties en hergebruik via functies en klassen
- Dezelfde taal als je applicatie (TypeScript)
Nadelen:
- Kleiner ecosysteem dan Terraform
- Meer keuzedruk (welke taal? welk pattern?)
AWS CDK
Als je exclusief op AWS zit, is CDK (Cloud Development Kit) een sterke keuze. Het genereert CloudFormation templates vanuit TypeScript of Python.
Voordelen:
- Diepe AWS-integratie, L2/L3 constructs met sensible defaults
- Goed voor pure AWS-shops
Nadelen:
- Alleen AWS (geen multi-cloud)
- CloudFormation-beperkingen onder de motorkap
Welke kies je?
| Situatie | Aanbeveling |
|---|---|
| Multi-cloud of meerdere SaaS-tools | Terraform |
| TypeScript-team, complexe logica nodig | Pulumi |
| 100% AWS, team kent CloudFormation | AWS CDK |
| Klein team, snel beginnen | Terraform |
Je eerste IaC-project opzetten
Stap 1: State storage configureren
IaC-tools houden een state file bij: een overzicht van wat er in de echte wereld bestaat en hoe dat mapt op je code. Deze state moet veilig en gedeeld opgeslagen worden.
# backend.tf — remote state in S3 met DynamoDB locking
terraform {
backend "s3" {
bucket = "mycompany-terraform-state"
key = "saas-platform/terraform.tfstate"
region = "eu-west-1"
encrypt = true
dynamodb_table = "terraform-locks"
}
}
Tip: Maak de state bucket en DynamoDB table handmatig of met een apart bootstrap-script aan. Dit is het enige stukje infrastructuur dat je niet met Terraform zelf beheert.
Stap 2: Projectstructuur
Een bewezen structuur voor SaaS-projecten:
infrastructure/
├── modules/
│ ├── networking/ # VPC, subnets, security groups
│ ├── database/ # RDS, Redis
│ ├── compute/ # ECS, Lambda, EC2
│ ├── cdn/ # CloudFront, S3 buckets
│ └── monitoring/ # CloudWatch, alerting
├── environments/
│ ├── dev/
│ │ ├── main.tf
│ │ ├── variables.tf
│ │ └── terraform.tfvars
│ ├── staging/
│ └── production/
├── global/ # IAM, Route53, shared resources
└── scripts/
└── bootstrap.sh # Eenmalige setup
Stap 3: Modules bouwen
Modules zijn herbruikbare bouwblokken. Hier een voorbeeld van een database-module:
# modules/database/main.tf
variable "environment" { type = string }
variable "vpc_id" { type = string }
variable "subnet_ids" { type = list(string) }
variable "instance_class" { type = string }
resource "aws_db_subnet_group" "main" {
name = "${var.environment}-db-subnet"
subnet_ids = var.subnet_ids
}
resource "aws_security_group" "database" {
name_prefix = "${var.environment}-db-"
vpc_id = var.vpc_id
ingress {
from_port = 5432
to_port = 5432
protocol = "tcp"
cidr_blocks = ["10.0.0.0/16"]
}
}
resource "aws_db_instance" "main" {
identifier = "${var.environment}-saas-db"
engine = "postgres"
instance_class = var.instance_class
# ... configuratie
}
output "endpoint" {
value = aws_db_instance.main.endpoint
}
Stap 4: CI/CD-integratie
Integreer IaC in je deployment pipeline zodat infrastructuurwijzigingen dezelfde review- en testcyclus doorlopen als applicatiecode:
# .github/workflows/infrastructure.yml
name: Infrastructure
on:
pull_request:
paths: ['infrastructure/**']
push:
branches: [main]
paths: ['infrastructure/**']
jobs:
plan:
runs-on: ubuntu-latest
if: github.event_name == 'pull_request'
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Init
run: terraform init
working-directory: infrastructure/environments/production
- name: Terraform Plan
run: terraform plan -no-color -out=tfplan
working-directory: infrastructure/environments/production
- name: Comment PR with Plan
uses: actions/github-script@v7
with:
script: |
// Post plan output als PR comment
apply:
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- uses: hashicorp/setup-terraform@v3
- name: Terraform Apply
run: terraform apply -auto-approve
working-directory: infrastructure/environments/production
Best practices voor SaaS-teams
1. Gebruik drift detection
Soms wijzigt iemand handmatig iets in de console. Detecteer dit automatisch:
# Draai dagelijks via cron
terraform plan -detailed-exitcode
# Exit code 2 = er zijn wijzigingen gedetecteerd
if [ $? -eq 2 ]; then
# Stuur alert naar Slack
curl -X POST "$SLACK_WEBHOOK" \
-d '{"text":"⚠️ Infrastructure drift gedetecteerd! Check Terraform plan."}'
fi
2. Tag alles
Tags zijn essentieel voor kostenbeheer en organisatie:
locals {
common_tags = {
Project = "saas-platform"
Environment = var.environment
ManagedBy = "terraform"
Team = "platform"
CostCenter = "engineering"
}
}
3. Gebruik prevent_destroy voor kritieke resources
resource "aws_db_instance" "main" {
# ...
lifecycle {
prevent_destroy = true
}
}
4. Secrets nooit in je code
Gebruik een secrets manager en refereer ernaar:
data "aws_secretsmanager_secret_version" "db_password" {
secret_id = "saas/production/db-password"
}
resource "aws_db_instance" "main" {
password = data.aws_secretsmanager_secret_version.db_password.secret_string
}
5. Implementeer policy-as-code
Tools als Open Policy Agent (OPA) of Sentinel laten je afdwingen dat infrastructuur aan je standaarden voldoet:
# policy/require-encryption.rego
package terraform
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_db_instance"
not resource.change.after.storage_encrypted
msg := "Database instances moeten versleuteld zijn"
}
Van nul naar productie: een realistisch stappenplan
Je hoeft niet alles in één keer te doen. Dit is een pragmatisch pad:
Week 1-2: Begin met je database en netwerk in Terraform. Laat de rest nog handmatig.
Week 3-4: Voeg compute resources toe (ECS tasks, Lambda's). Zet remote state op.
Maand 2: Integreer in CI/CD. Voeg monitoring-resources toe. Begin met drift detection.
Maand 3+: Voeg policy-as-code toe. Documenteer modules. Train het team.
De sleutel is incrementeel adopteren. Probeer niet je hele infrastructuur in één keer te migreren — dat is een recept voor frustratie.
Conclusie
Infrastructure as Code is geen luxe meer voor SaaS-teams — het is een noodzaak zodra je voorbij de MVP-fase bent. Het verschil tussen teams die weken besteden aan infrastructuurproblemen en teams die in minuten nieuwe omgevingen opspinnen, is bijna altijd IaC.
Begin klein: pak je database of je netwerkconfiguratie. Beschrijf het in Terraform of Pulumi. Commit het naar Git. En bouw van daaruit verder.
De investering betaalt zich terug bij je eerste incident, je eerste nieuwe teamlid, of je eerste grote klant die een aparte omgeving nodig heeft. En dan ben je blij dat je het hebt gedaan.