Production-grade guide to finops commitment management covering architecture patterns, implementation strategies, testing approaches, and operational best practices for enterprise engineering teams.
FinOps Commitment Management is the process of planning, executing, monitoring, and optimizing reserved and committed cloud capacity across infrastructure and services. It matters when cloud spend grows large enough that upfront commitments—such as AWS Reserved Instances, Azure Reserved VMs, or Google Cloud Committed Use Discounts—become a significant portion of the total cost, and where failing to align commitments with actual usage leads to underutilization, overprovisioning, and wasted capital.
To plan commitments, teams determine which workloads are stable enough to justify a long-term commitment. The process starts with identifying predictable workloads—those with steady CPU, memory, and I/O profiles over at least 60 days.
A typical planning workflow begins with a query that extracts historical utilization data from a cloud provider's metrics API. Using curl, teams fetch 90-day usage data for a set of instances:
curl \
-H "Authorization: Bearer $AWS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"StartTime": "2024-01-01T00:00:00Z",
"EndTime": "2024-03-31T23:59:59Z",
"Metrics": ["CPUUtilization", "NetworkIn", "NetworkOut"],
"Period": "86400",
"Statistics": ["Average", "Minimum", "Maximum"],
"Dimensions": [
{ "Name": "InstanceId", "Value": "i-12345678" }
]
}' \
https://cloudwatch.us-east-1.amazonaws.com/v20100801/GetMetricStatistics
The response includes a Datapoints array with Timestamp, Average, Minimum, Maximum, and Unit. A script then computes the 90th percentile of CPU utilization across the period. Workloads with a 90th percentile above 60% and a coefficient of variation (standard deviation / mean) below 0.3 are candidates for commitment.
The output of this analysis is a list of instance types and their utilization profiles. A commitments.yaml file is generated:
- workload: "backend-api"
instance_type: "r6i.4xlarge"
min_capacity: 4
max_capacity: 12
target_utilization: 0.65
duration: "36-month"
target_commitment: 12000
region: "us-west-2"
estimated_cost: 180000
current_rsvd_instances: 6
current_rsvd_cost: 108000
This file drives the next step: commitment proposal and approval.
Once approved, commitments are executed via a cloud provider’s API or a custom orchestration system. The execution workflow relies on a commitment service that maintains the state of each commitment.
Each commitment is tracked in a finops.commitments table in a PostgreSQL database:
CREATE TABLE finops.commitments (
id UUID PRIMARY KEY,
workload_name TEXT NOT NULL,
instance_type TEXT NOT NULL,
region TEXT NOT NULL,
duration INTERVAL NOT NULL,
quantity INTEGER NOT NULL,
effective_date TIMESTAMP WITH TIME ZONE NOT NULL,
status TEXT CHECK (status IN ('pending', 'active', 'overdue', 'expired')),
commit_cost NUMERIC(15,2) NOT NULL,
applied_cost NUMERIC(15,2),
last_updated TIMESTAMP WITH TIME ZONE,
metadata JSONB
);
A commit command triggers the creation of a new commitment:
curl \
-X POST \
-H "Content-Type: application/json" \
-d '{
"workload_name": "analytics-pipeline",
"instance_type": "c5.8xlarge",
"region": "eu-central-1",
"duration": "P36M",
"quantity": 20,
"effective_date": "2024-04-01T00:00:00Z"
}' \
https://api.finops.example.com/v1/commitments
The service responds with a 202 Accepted and a Location header pointing to the new commitment:
HTTP/1.1 202 Accepted
Location: /v1/commitments/7a6b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d
Content-Type: application/json
{
"id": "7a6b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"status": "pending",
"message": "Commitment created; awaiting provider confirmation"
}
The commitment is then processed asynchronously. A background worker polls the cloud provider’s API every 15 minutes to check the status of the commitment. It uses GET /v1/commitments/{id} and updates the database on every change.
Monitoring begins immediately after a commitment becomes active. The service runs a daily check to evaluate whether each commitment is meeting its targets.
A monitoring script queries the finops.commitments table and compares current utilization against committed capacity:
#!/bin/bash
while IFS= read -r id; do
# Fetch commitment details
commit_data=$(curl -s "https://api.finops.example.com/v1/commitments/$id")
instance_type=$(echo "$commit_data" | jq -r '.instance_type')
region=$(echo "$commit_data" | jq -r '.region')
quantity=$(echo "$commit_data" | jq -r '.quantity')
# Fetch current usage from cloud provider
usage_data=$(curl \
-H "Authorization: Bearer $AWS_ACCESS_TOKEN" \
-H "Content-Type: application/json" \
-d "{
\"StartTime\": \"$(date -u -d 'now -1 day' +'%Y-%m-%dT%H:%M:%SZ')\",
\"EndTime\": \"$(date -u +'%Y-%m-%dT%H:%M:%SZ')\",
\"Metrics\": [\"CPUUtilization\"],
\"Period\": \"3600\",
\"Statistics\": [\"Average\"],
\"Dimensions\": [
{ \"Name\": \"InstanceType\", \"Value\": \"$instance_type\" },
{ \"Name\": \"Region\", \"Value\": \"$region\" }
]
}" \
https://cloudwatch.us-east-1.amazonaws.com/v20100801/GetMetricStatistics)
avg_utilization=$(echo "$usage_data" | jq -r '.Datapoints | map(.Average) | add / length')
# Compute utilization ratio
utilization_ratio=$(echo "$avg_utilization" | awk '{printf "%.4f", $1}')
# Update commitment
curl \
-X PATCH \
-H "Content-Type: application/json" \
-d "{
\"current_utilization\": $utilization_ratio,
\"utilization_status\": \"$(echo "$utilization_ratio" | awk '{if ($1 >= 0.8) print "overutilized"; else if ($1 <= 0.5) print "underutilized"; else print "optimal'}')\"
}" \
"https://api.finops.example.com/v1/commitments/$id"
done < <(psql -t -c "SELECT id FROM finops.commitments WHERE status = 'active'")
A commitment is flagged as underutilized if its average CPU utilization over the past 30 days is below 50%. The system logs a warning event in a finops.events table:
INSERT INTO finops.events (
id,
type,
entity_type,
entity_id,
severity,
message,
metadata
) VALUES (
gen_random_uuid(),
'commitment-utilization-warning',
'commitment',
'7a6b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d',
'warning',
'Average utilization 43% for 30 days; below threshold of 50%',
'{"utilization": 0.43, "threshold": 0.5, "period": "30d"}'
);
Adjustments are made when a commitment is underutilized or overutilized. The adjustment workflow allows for commitment rebalancing—changing the quantity, duration, or instance type of an active commitment.
To adjust a commitment, a team submits a rebalance request:
POST /v1/commitments/7a6b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d/rebalance HTTP/1.1
Content-Type: application/json
Authorization: Bearer $ADMIN_TOKEN
{
"new_quantity": 14,
"new_duration": "P24M",
"new_instance_type": "r6i.8xlarge",
"reason": "Workload growth exceeds 60% utilization; need higher memory capacity"
}
The service validates the request and updates the commitment’s metadata field:
{
"current_quantity": 20,
"current_duration": "P36M",
"current_instance_type": "c5.8xlarge",
"new_quantity": 14,
"new_duration": "P24M",
"new_instance_type": "r6i.8xlarge",
"reason": "Workload growth exceeds 60% utilization; need higher memory capacity"
}
The system then schedules a commitment adjustment batch job that runs nightly. This job:
status = 'active'suggest-adjustment function that evaluates:The batch job outputs a list of proposed adjustments in a commitments.suggestions table:
CREATE TABLE finops.commitments.suggestions (
id UUID PRIMARY KEY,
commitment_id UUID REFERENCES finops.commitments(id),
action TEXT CHECK (action IN ('reduce_quantity', 'increase_quantity', 'change_type', 'extend_duration')),
cost_impact NUMERIC(12,2),
savings NUMERIC(12,2),
justification TEXT,
created_at TIMESTAMP WITH TIME ZONE
);
A suggest-adjustment function, implemented in Python, computes the impact of a change:
def suggest_adjustment(commitment, current_usage, target_utilization=0.65):
avg_utilization = current_usage['avg']
quantity = commitment['quantity']
instance_type = commitment['instance_type']
duration = commitment['duration']
# Determine if current usage is high or low
if avg_utilization > target_utilization * 1.2:
return {
"action": "increase_quantity",
"cost_impact": quantity * 0.15 * 200, # 15% cost per instance
"savings": 0.0, # no savings yet
"justification": f"Current utilization {avg_utilization:.2f} > 1.2 × target; increasing quantity"
}
elif avg_utilization < target_utilization * 0.8:
return {
"action": "reduce_quantity",
"cost_impact": -quantity * 0.15 * 200,
"savings": 0.3 * quantity * 200,
"justification": f"Current utilization {avg_utilization:.2f} < 0.8 × target; reducing quantity"
}
else:
return {
"action": "no_change",
"cost_impact": 0,
"savings": 0,
"justification": f"Utilization within 20% of target: {avg_utilization:.2f}"
}
The most common silent failure is commitment drift: a commitment becomes active but is never properly monitored. The status column in finops.commitments is often stuck at pending because the background worker fails to update it after the cloud provider returns a 202 Accepted with no final 200 OK.
This happens when the commitment service does not poll the provider’s GetCommitmentStatus API after the initial POST. The service must handle the case where the provider returns 202 Accepted but the final status is not available until 10–30 minutes later.
Another edge: duration mismatch. A 3-year commitment is defined as P36M, but the provider expects P3Y. When the service sends P36M, the commitment is processed as 3 years, but the billing cycle starts at the end of the 36th month, not the 37th. This causes a month gap in the first year.
A third sharp edge: commitment overlap. When a new commitment is created before the previous one expires, two commitments can overlap. The system must track commitment lifecycles with a finops.commitments.history table that logs every state transition:
CREATE TABLE finops.commitments.history (
id UUID PRIMARY KEY,
commitment_id UUID REFERENCES finops.commitments(id),
old_status TEXT,
new_status TEXT,
changed_at TIMESTAMP WITH TIME ZONE,
notes TEXT
);
The commitment service must emit a commitment-overlap event when two active commitments exist with overlapping effective_date and expiration_date:
{
"type": "commitment-overlap",
"commitment_id": "7a6b8c9d-1e2f-3a4b-5c6d-7e8f9a0b1c2d",
"overlapping_with": "b1c2d3e4-f5g6-h7i8-j9k0-l1m2n3o4p5q6",
"overlap_start": "2024-05-01T00:00:00Z",
"overlap_end": "2024-10-31T23:59:59Z",
"total_overlap_days": 184
}
A monthly retrospective uses a commitments.report table to summarize performance:
CREATE TABLE finops.commitments.report (
id UUID PRIMARY KEY,
period DATE,
total_commitments INTEGER,
total_spend NUMERIC(15,2),
total_utilization_avg NUMERIC(5,4),
underutilized_count INTEGER,
overutilized_count INTEGER,
adjustment_suggestions_count INTEGER,
created_at TIMESTAMP WITH TIME ZONE
);
The report is generated by a generate-commitment-report script that joins commitments, events, and suggestions and outputs a JSON summary:
{
"period": "2024-04",
"total_commitments": 14,
"total_spend": 214700.50,
"total_utilization_avg": 0.63,
"underutilized_count": 5,
"overutilized_count": 3,
"adjustment_suggestions_count": 8,
"summary": "Five commitments underutilized; three overutilized. Recommendations include reducing quantity for analytics-pipeline and extending duration for backend-api."
}
This report is the foundation of the FinOps team’s quarterly review. It is not a metric dashboard—it is a narrative of commitment decisions, their outcomes, and the learning that drives future planning.
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