Manage technology change in enterprises. Covers ITIL change management, CAB processes, change risk assessment, progressive rollouts, and balancing governance with engineering velocity.
Enterprise Change Management for Technology is the disciplined practice of planning, executing, and governing software and infrastructure changes across a large, distributed organisation. It matters when a new feature, system integration, or platform upgrade must roll out reliably across multiple teams, systems, and environments—especially when failure in production has cascading consequences. It is the backbone of technology delivery at scale, ensuring that changes from development to production are predictable, traceable, and reversible.
Change introductions begin with a clear, shared understanding of what is changing, why, and how it affects existing systems. A change introduction must be documented in a change request (CR), which includes the following core elements:
CHG-2024-0127).feature, bugfix, enhancement, infrastructure, configuration, migration, or security.finance/erp/transactions, sales/d365/quotes).dependencies.json file:{
"dependencies": [
{
"system": "hr/payroll",
"version": "2024.03",
"required-by": "2024-07-15",
"status": "pending",
"notes": "Payroll must support new tax code format before payroll run."
},
{
"system": "logistics/warehouse",
"version": "v4.1",
"required-by": "2024-07-10",
"status": "verified",
"notes": "Warehouse must accept batch IDs from ERP before shipping."
}
]
}
A change introduction is not complete until it includes a risk assessment and rollback plan. Risks are recorded as a list of tuples: (risk, probability, impact, mitigation). For example:
- Risk: ERP integration fails during peak load
- Probability: high
- Impact: high
- Mitigation: pre-load test data, enable throttling on API gateway, monitor queue depth
- Risk: Database migration fails on first run
- Probability: medium
- Impact: medium
- Mitigation: validate schema migration script, use point-in-time backup, enable incremental migration
Deployment is a staged process governed by a deployment pipeline defined in a pipeline.yaml file, using standard CI/CD tooling. The pipeline defines stages, each with specific commands, configuration, and validation steps.
pipeline:
stages:
- name: build
steps:
- run: npm run build
- run: docker build -t app:${VERSION} .
- run: docker push app:${VERSION}
- name: test
steps:
- run: npm run test:unit
- run: npm run test:integration
- run: psql -d testdb -c "SELECT validate_data_integrity();"
- run: curl -s -H "Authorization: Bearer $API_KEY" http://test-api:8080/health
- name: deploy-staging
steps:
- run: kubectl apply -f k8s/staging/
- run: kubectl rollout status deployment/app-staging
- run: kubectl patch deployment/app-staging -p '{"spec":{"replicas":5}}'
- name: promote-to-prod
steps:
- run: kubectl set image deployment/app-prod app=app:v1.2.3
- run: kubectl rollout status deployment/app-prod --timeout=300s
- run: kubectl rollout undo deployment/app-prod --to-revision=2
Each stage has a runbook that defines pre- and post-checks. A pre-check is a command or set of commands that must pass before a stage begins. For instance, the deploy-staging stage requires the following pre-checks:
psql -d staging-erp -c "SELECT 1 FROM pg_catalog.pg_database WHERE datname = 'staging-erp';"
# Pre-check: Verify API gateway is up and routing
curl -f -H "Host: staging.erp.company.com" http://api-gateway:8080/health
# Pre-check: Verify configuration is deployed
diff <(kubectl get configmap app-config -o jsonpath='{.data}') <(cat config/staging-config.json)
Post-checks run after a stage completes and are validated via a verify.yaml file in the deployment directory:
verify:
- name: "API health check"
command: "curl -s http://app-staging:8080/health | jq -e '.status == \"healthy\"'"
timeout: "60s"
- name: "Queue depth monitoring"
command: "kafka-topics.sh --bootstrap-server kafka:9092 --describe --topic orders"
expected: "High watermark: 10000"
retries: 3
Dependencies between changes are managed through a change dependency graph, where each change is a node and each dependency is a directed edge. The graph is maintained in a dependency-graph.json file, which is updated by a change manager after every deployment.
{
"edges": [
{
"from": "CHG-2024-0127",
"to": "CHG-2024-0151",
"type": "upstream",
"required-by": "2024-08-01",
"status": "in-progress"
},
{
"from": "CHG-2024-0151",
"to": "CHG-2024-0173",
"type": "downstream",
"required-by": "2024-08-10",
"status": "blocked"
}
]
}
Changes are considered ready only when all upstream dependencies are completed and verified. A change is blocked if any required dependency is not yet verified. A change manager runs a daily check-dependencies.sh script to surface issues:
#!/bin/bash
# check-dependencies.sh
set -euo pipefail
DEPGRAPH=$(cat dependency-graph.json)
for edge in $(echo "$DEPGRAPH" | jq -r '.edges[] | @json'); do
FROM=$(echo "$edge" | jq -r '.from')
TO=$(echo "$edge" | jq -r '.to')
REQUIRED_BY=$(echo "$edge" | jq -r '.required-by')
STATUS=$(curl -s http://change-manager/api/changes/$FROM | jq -r '.status')
if [[ "$STATUS" != "completed" ]]; then
echo "Change $FROM not completed; blocking $TO"
continue
fi
VERIFIED=$(curl -s http://change-manager/api/changes/$FROM | jq -r '.verification.status')
if [[ "$VERIFIED" != "passed" ]]; then
echo "Change $FROM not verified; blocking $TO"
continue
fi
NOW=$(date -I)
if [[ "$NOW" > "$REQUIRED_BY" ]]; then
echo "Change $FROM overdue for $TO; deadline was $REQUIRED_BY"
fi
done
After deployment, the change’s impact is tracked through impact indicators defined in a impact-indicators.yaml file. Each indicator is a query or metric that measures the success or health of a change.
impact-indicators:
- name: "Order processing latency"
query: |
SELECT avg(duration_ms)
FROM orders
WHERE created_at >= '2024-07-15'
AND created_at < '2024-07-16'
threshold: "400ms"
target: "300ms"
alert: true
severity: "critical"
- name: "User login success rate"
query: |
SELECT
count(*) FILTER (WHERE success = true) * 100.0 / count(*) AS success_rate
FROM user_sessions
WHERE session_start >= '2024-07-15'
threshold: "95%"
target: "98%"
alert: true
severity: "warning"
A change is considered successful if all critical indicators meet their thresholds within 48 hours of deployment. A change impact report is generated automatically using a generate-impact-report.sh script:
#!/bin/bash
# generate-impact-report.sh
set -euo pipefail
CHG_ID=$1
OUTPUT_DIR="reports/$CHG_ID"
mkdir -p "$OUTPUT_DIR"
for indicator in $(ls impact-indicators.yaml | jq -r '.[] | @json'); do
NAME=$(echo "$indicator" | jq -r '.name')
QUERY=$(echo "$indicator" | jq -r '.query')
THRESHOLD=$(echo "$indicator" | jq -r '.threshold')
RESULT=$(psql -d production -c "$QUERY" -t -A)
if [[ "$RESULT" > "$THRESHOLD" ]]; then
STATUS="success"
else
STATUS="failed"
fi
cat > "$OUTPUT_DIR/$NAME.md" <<EOF
## $NAME
- Threshold: $THRESHOLD
- Actual: $RESULT
- Status: $STATUS
- Query: $QUERY
EOF
done
# Generate summary
cat > "$OUTPUT_DIR/summary.md" <<EOF
# Change Impact Report: $CHG_ID
Generated: $(date)
## Summary
- All indicators: $(ls "$OUTPUT_DIR" | wc -l) indicators evaluated
- Success: $(find "$OUTPUT_DIR" -name "*.md" -exec grep -l "Status: success" {} \; | wc -l) of $(ls "$OUTPUT_DIR" | wc -l)
EOF
When a change fails, the change failure state machine is triggered. A change is in one of the following states: planned, in-progress, verified, completed, failed, rollback-in-progress, rolled-back.
A change fails when any critical impact indicator fails, or when a deployment stage fails to pass its post-checks. The failure is logged in a change-events.log file, with each event in a JSON-lined format:
{"timestamp": "2024-07-15T10:23:45Z", "change": "CHG-2024-0127", "event": "deployment-stage-failed", "stage": "deploy-staging", "details": {"error": "Timeout waiting for rollout", "exit-code": 1, "log": "kubectl rollout status deployment/app-staging timed out"}}
{"timestamp": "2024-07-15T10:25:10Z", "change": "CHG-2024-0127", "event": "impact-indicator-failed", "indicator": "Order processing latency", "actual": "520ms", "threshold": "400ms", "details": {"query": "SELECT avg(duration_ms) FROM orders WHERE created_at >= '2024-07-15'"}}
Upon failure, the change manager runs trigger-rollback.sh, which:
pipeline.yaml to include a rollback stage.change-status.json file.{
"change": "CHG-2024-0127",
"status": "failed",
"failure-reason": "Order processing latency exceeded threshold",
"last-updated": "2024-07-15T10:25:10Z",
"rollback": {
"started": true,
"stage": "rollback-in-progress",
"target-version": "v1.2.2",
"steps": [
"kubectl rollout undo deployment/app-prod --to-revision=1",
"psql -d production -c \"UPDATE settings SET value = 'rollback' WHERE key = 'maintenance-mode';\"",
"curl -X POST http://alerting:8080/api/alert -d '{\"message\": \"Rollback initiated for CHG-2024-0127\"}'"
]
}
}
verify.yaml file is often ignored because it is not versioned with the deployment. Teams assume it is part of the k8s/ directory, but it is not checked into the main repository. A change fails silently when the verify.yaml is out of sync with the pipeline.dependencies.json file is often updated manually instead of being generated by the CI system. This leads to stale dependencies and missed rollout deadlines.impact-indicators.yaml is frequently underused. Teams define indicators but fail to run the generate-impact-report.sh script regularly. Reports are collected manually, leading to delayed feedback.pipeline.yaml often fail silently. A curl command may return 200 OK, but the response body is not validated. A psql command may run but not return the expected result set. The verify.yaml file is the only place where these expectations are captured.change-status.json file has it as “in-progress”, the team is confused and manual reconciliation is needed.rollback stage in the pipeline is missing the kubectl rollout undo command, which causes a 10-minute downtime during rollback.CHG-2024-0127 change is deployed, but the hr/payroll system is not yet ready.impact-indicators.yaml is not run in the weekly review.Enterprise Change Management for Technology is not a checklist. It is a living practice—where every change leaves behind evidence, every failure teaches, and every success is measurable.
This page was rewritten on 17 October 2026. It replaced a templated version that was not specific to its own title. How these pages are written and checked. If anything here is wrong, tell us at [email protected] and we will correct it.
We use cookies for analytics (Google Analytics) and advertising (Google AdSense) to improve your experience and support free content. Privacy Policy