Sessão 040 — FinOps: Savings Plans vs Reserved Instances — diferenças e flexibilidade
Dependências: nenhuma (tópico independente)
Objetivo
Ao final desta sessão, você conseguirá comparar Compute Savings Plans, EC2 Instance Savings Plans e Reserved Instances por flexibilidade de instância, escopo regional vs zonal e desconto; calcular o ROI de cada opção para um perfil de workload específico; e entender o risco de over-commitment.
Contexto
[FATO] On-Demand pricing é o modelo padrão: você paga por hora de uso sem compromisso. AWS oferece descontos substanciais em troca de compromisso de uso por 1 ou 3 anos. Os dois mecanismos principais são Savings Plans (compromisso em $/hora de uso) e Reserved Instances (compromisso em capacidade específica).
[FATO] AWS lançou Savings Plans em novembro de 2019 como evolução dos Reserved Instances, com maior flexibilidade. A própria AWS recomenda Savings Plans sobre Reserved Instances para a maioria dos casos de uso — mas Reserved Instances ainda oferecem vantagens específicas (capacity reservation, desconto zonal).
Conceitos principais
1. Quatro tipos de Savings Plans
[FATO] AWS oferece quatro tipos de Savings Plans:
Tipo Desconto max Serviços cobertos
────────────────────────────────────────────────────────────────────
Compute Savings Plans até 66% EC2 (qualquer família/tamanho/
região/OS/tenancy), Fargate,
Lambda
EC2 Instance até 72% EC2 dentro de uma família
Savings Plans específica em uma região
específica (ex: m5 em us-east-1)
— qualquer tamanho/OS/tenancy
Database Savings Plans até 35% Aurora, RDS, DynamoDB,
ElastiCache, DocumentDB,
Timestream, Neptune, Keyspaces,
DMS, OpenSearch
SageMaker AI até 64% SageMaker AI — qualquer família/
Savings Plans tamanho/região/componente
────────────────────────────────────────────────────────────────────
[FATO] Savings Plans comprometem um valor em $/hora (não um número de instâncias). Se você usa mais do que o comprometido, o excedente é cobrado em On-Demand. Se usa menos, você paga pelo comprometido mesmo sem uso.
2. Tipos de Reserved Instances (RIs) para EC2
[FATO] Reserved Instances para EC2 têm dois tipos principais por escopo de flexibilidade:
Tipo Desconto max Flexibilidade
────────────────────────────────────────────────────────────────────
Standard RI até 72% Família, tamanho, OS e região
fixos. Size flexibility em RIs
regionais (dentro da família).
Pode vender no Marketplace.
Convertible RI até 66% Pode fazer exchange para mudar
família, tamanho, OS ou tenancy.
Exchange é manual (não automático).
NÃO pode vender no Marketplace.
────────────────────────────────────────────────────────────────────
[FATO] Escopo de RI — Regional vs. Zonal:
Escopo Regional (recomendado):
- Desconto aplicado a qualquer instância na região
- Instance size flexibility: desconto se aplica
automaticamente a outros tamanhos da mesma família
(ex: comprou m5.large — aplica em m5.xlarge, m5.2xlarge etc.)
- SEM reserva de capacidade garantida
Escopo Zonal (específico por AZ):
- Desconto aplicado apenas à AZ especificada
- SEM size flexibility (instância exata)
- COM reserva de capacidade garantida nessa AZ
- Pode ser vendido no Marketplace (Standard RI)
3. Tabela comparativa completa
[FATO — AWS Docs]:
Compute EC2 Instance Convertible Standard
SP SP RI RI
─────────────────────────────────────────────────────────────────────────
Desconto máx. 66% 72% 66% 72%
Compromisso $/hora $/hora # instâncias # instâncias
Família flexível ✓ — manual —
Tamanho flexível ✓ ✓ manual regional only
OS flexível ✓ ✓ manual —
Tenancy flexível ✓ ✓ manual —
Cross-region ✓ — — —
Cobre Fargate ✓ — — —
Cobre Lambda ✓ — — —
Capacity reservation — — zonal only zonal only
Cancelamento — — — —
Exchange/modificação N/A N/A ✓ (manual) limitado
Venda no Marketplace — — — ✓ (zonal)
─────────────────────────────────────────────────────────────────────────
✓ = automático; — = não disponível; manual = requer ação explícita
4. Opções de pagamento e impacto no desconto
[FATO] Todos os tipos de Savings Plans e RIs oferecem três opções de pagamento:
Pagamento Compromisso Desconto
────────────────────────────────────────────────────────────────
All Upfront 100% adiantado Máximo (66%, 72% etc.)
Partial Upfront ~50% adiantado Intermediário
No Upfront Zero adiantado Menor (ainda substancial)
Prazo de 3 anos > prazo de 1 ano em desconto para todas as opções.
Exemplo (m5.xlarge Linux us-east-1):
On-Demand: $0.192/hora = $1.684/mês
Standard RI 1y All Up: $0.110/hora = $965/mês → 43% off
Standard RI 3y All Up: $0.069/hora = $605/mês → 64% off
Compute SP 1y All Up: $0.116/hora = $1.018/mês → 40% off
Compute SP 3y All Up: $0.073/hora = $640/mês → 62% off
EC2 Instance SP 1y: $0.109/hora = $957/mês → 43% off
[INCERTO] Os valores exatos de desconto variam por região, família de instância e OS — sempre verifique o pricing calculator da AWS para o seu caso específico, pois os percentuais mudam periodicamente.
5. Como Savings Plans são aplicados
[FATO] A aplicação de Savings Plans segue uma hierarquia:
Ordem de aplicação:
1. Savings Plans cobrem primeiro as instâncias com MENOR preço
On-Demand no seu portfólio (maximiza cobertura)
2. EC2 Instance SP (mais específico) é aplicado ANTES de
Compute SP (mais genérico)
3. O que exceder o compromisso $/hora → cobrado On-Demand
Exemplo:
Você tem Compute SP de $1.00/hora (3 anos, no upfront)
Suas instâncias custam:
- m5.large Linux us-east-1: $0.096/hora On-Demand
- c5.xlarge Linux eu-west-1: $0.192/hora On-Demand
Com Compute SP, você paga o preço SP em vez do On-Demand
para as instâncias que cobrem o commitment:
~$1.00/hora → cobre essas instâncias com desconto de ~60%
Acima disso → On-Demand
[FATO] Savings Plans não fornecem capacity reservation. Se você precisa garantir capacidade em uma AZ específica (ex: failover crítico), use On-Demand Capacity Reservation (ODCR) — Savings Plans se aplicam sobre o ODCR.
6. Análise de ROI e risco de over-commitment
[CONSENSO] O risco central de Savings Plans e RIs é o over-commitment: comprometer mais do que você usa. O comprometimento é irrevogável durante o prazo — você paga mesmo sem uso.
Framework de decisão:
─────────────────────────────────────────────────────────────
Baseline usage → Comprometer (Savings Plans / RI)
Variável mas previsível → Comprometer baseline, On-Demand para picos
Imprevisível → On-Demand (ou Spot para tolerantes a interrupção)
Regra prática:
Comprometa no máximo o uso do seu P10 (percentil 10)
— o uso que você tem 90% do tempo como mínimo garantido.
Nunca comprometa o uso médio se houver sazonalidade,
pois nos períodos abaixo da média você paga sem receber.
Calculando break-even (Savings Plans 1 ano vs. On-Demand):
On-Demand: $0.192/hora × 8.760h/ano = $1.682/ano
Compute SP 1y: $0.116/hora × 8.760h/ano = $1.016/ano (66% utilização)
Break-even: você precisa usar a instância pelo menos X% do tempo
para o SP ser mais barato que On-Demand:
Break-even % = SP_price / OD_price = 0.116 / 0.192 = 60.4%
→ Se a instância ficar ativa > 60.4% do tempo: SP é mais barato
→ Se ficar ativa < 60.4% do tempo: On-Demand seria mais barato
Exemplo prático
Cenário: avaliando a estratégia FinOps para uma plataforma de e-commerce
Workload:
- 10 instâncias m5.xlarge Linux em us-east-1 rodando 24/7 (web tier estável)
- 5 instâncias c5.2xlarge Linux em us-east-1 rodando 70% do tempo (processamento batch)
- Lambda functions (1.000.000 invocações/mês, 512MB, 500ms avg duration)
- Fargate tasks (3.000 vCPU-hora/mês, 6.000 GB-hora/mês)
CDK Python — Cost Anomaly Detection + Budget alert
from aws_cdk import (
Stack,
aws_budgets as budgets,
aws_ce as ce, # Cost Explorer
)
from constructs import Construct
class FinOpsCostControlStack(Stack):
def __init__(self, scope: Construct, construct_id: str, **kwargs):
super().__init__(scope, construct_id, **kwargs)
# ── Budget: alerta quando custo mensal exceder $10.000 ────────
monthly_budget = budgets.CfnBudget(
self, "MonthlyComputeBudget",
budget=budgets.CfnBudget.BudgetDataProperty(
budget_name="monthly-compute-budget",
budget_type="COST",
time_unit="MONTHLY",
budget_limit=budgets.CfnBudget.SpendProperty(
amount=10000,
unit="USD",
),
cost_filters={
"Service": ["Amazon Elastic Compute Cloud - Compute",
"AWS Lambda",
"AWS Fargate"],
},
cost_types=budgets.CfnBudget.CostTypesProperty(
include_tax=True,
include_subscription=True,
use_blended=False,
),
),
notifications_with_subscribers=[
budgets.CfnBudget.NotificationWithSubscribersProperty(
notification=budgets.CfnBudget.NotificationProperty(
comparison_operator="GREATER_THAN",
notification_type="ACTUAL", # custo real (não forecast)
threshold=80, # 80% do budget
threshold_type="PERCENTAGE",
),
subscribers=[
budgets.CfnBudget.SubscriberProperty(
address="finops@company.com",
subscription_type="EMAIL",
),
],
),
budgets.CfnBudget.NotificationWithSubscribersProperty(
notification=budgets.CfnBudget.NotificationProperty(
comparison_operator="GREATER_THAN",
notification_type="FORECASTED", # forecast excede budget
threshold=100,
threshold_type="PERCENTAGE",
),
subscribers=[
budgets.CfnBudget.SubscriberProperty(
address="finops@company.com",
subscription_type="EMAIL",
),
],
),
],
)
# ── Cost Anomaly Detection ────────────────────────────────────
# Detecta anomalias de custo automaticamente (ML-based)
anomaly_monitor = ce.CfnAnomalyMonitor(
self, "ComputeCostMonitor",
monitor_name="compute-cost-monitor",
monitor_type="DIMENSIONAL",
monitor_dimension="SERVICE",
)
anomaly_subscription = ce.CfnAnomalySubscription(
self, "ComputeAnomalyAlert",
subscription_name="compute-anomaly-alert",
monitor_arn_list=[anomaly_monitor.attr_monitor_arn],
subscribers=[
ce.CfnAnomalySubscription.SubscriberProperty(
address="finops@company.com",
type="EMAIL",
status="CONFIRMED",
),
],
# Alerta quando impacto total exceder $100
threshold_expression=ce.CfnAnomalySubscription.ExpressionProperty(
dimensions=ce.CfnAnomalySubscription.DimensionValuesProperty(
key="ANOMALY_TOTAL_IMPACT_ABSOLUTE",
values=["100"],
match_options=["GREATER_THAN_OR_EQUAL"],
)
),
frequency="DAILY",
)
Cálculo de ROI — Python (análise offline)
"""
Script de análise FinOps: calcula ROI de Savings Plans vs On-Demand
para o perfil de workload descrito no cenário.
Preços aproximados us-east-1 (verificar sempre no pricing calculator):
https://aws.amazon.com/ec2/pricing/reserved-instances/pricing/
"""
from dataclasses import dataclass
from typing import Literal
@dataclass
class WorkloadComponent:
name: str
on_demand_hourly: float
utilization_pct: float # 0.0 – 1.0
count: int
hours_per_year: float = 8760.0
def annual_on_demand_cost(w: WorkloadComponent) -> float:
return w.on_demand_hourly * w.utilization_pct * w.hours_per_year * w.count
def annual_savings_plan_cost(
w: WorkloadComponent,
sp_hourly_rate: float,
) -> float:
"""
Savings Plan é sempre cobrado pelo compromisso (sp_hourly_rate * count),
independente da utilização — por isso over-commitment é perigoso.
"""
committed = sp_hourly_rate * w.hours_per_year * w.count
return committed
def break_even_utilization(
on_demand_rate: float,
sp_rate: float,
) -> float:
"""Utilização mínima para SP ser mais barato que On-Demand."""
return sp_rate / on_demand_rate
def analyze_workload():
# ── Workload components ───────────────────────────────────────────
web_tier = WorkloadComponent(
name="Web tier (m5.xlarge, 10x)",
on_demand_hourly=0.192, # m5.xlarge Linux us-east-1
utilization_pct=1.0, # 100% — sempre ligado
count=10,
)
batch_tier = WorkloadComponent(
name="Batch tier (c5.2xlarge, 5x)",
on_demand_hourly=0.340, # c5.2xlarge Linux us-east-1
utilization_pct=0.70, # 70% do tempo
count=5,
)
# ── Preços aproximados Savings Plans 1y No Upfront ────────────────
# NOTA: sempre verifique o pricing atual em aws.amazon.com
WEB_SP_RATE = 0.116 # Compute SP ~40% off On-Demand (m5.xlarge)
BATCH_SP_RATE = 0.204 # Compute SP ~40% off On-Demand (c5.2xlarge)
print("=" * 65)
print("ANÁLISE FINOPS — Savings Plans vs On-Demand")
print("=" * 65)
for workload, sp_rate in [(web_tier, WEB_SP_RATE), (batch_tier, BATCH_SP_RATE)]:
od_annual = annual_on_demand_cost(workload)
sp_annual = annual_savings_plan_cost(workload, sp_rate)
savings = od_annual - sp_annual
be_util = break_even_utilization(workload.on_demand_hourly, sp_rate)
print(f"\n{workload.name}")
print(f" On-Demand anual: ${od_annual:,.0f}")
print(f" Savings Plan anual: ${sp_annual:,.0f}")
print(f" Economia: ${savings:,.0f} ({savings/od_annual*100:.1f}%)")
print(f" Break-even utilização: {be_util*100:.1f}%")
print(f" Utilização atual: {workload.utilization_pct*100:.0f}%")
print(f" → {'✓ SP RECOMENDADO' if workload.utilization_pct > be_util else '✗ On-Demand mais barato'}")
# ── Risco de over-commitment no batch tier ────────────────────────
print("\n--- ANÁLISE DE RISCO (Batch tier) ---")
print("Cenário: utilização cai para 40% (metade do esperado)")
batch_worst = WorkloadComponent(
name="Batch tier — worst case",
on_demand_hourly=0.340,
utilization_pct=0.40, # pior caso
count=5,
)
od_worst = annual_on_demand_cost(batch_worst)
sp_annual = annual_savings_plan_cost(batch_tier, BATCH_SP_RATE)
waste = sp_annual - od_worst
print(f" On-Demand (40% util): ${od_worst:,.0f}")
print(f" Savings Plan (fixo): ${sp_annual:,.0f}")
print(f" Desperdício: ${waste:,.0f} (pagando sem usar)")
print(f" → RECOMENDAÇÃO: comprometa apenas o baseline seguro (P10)")
if __name__ == "__main__":
analyze_workload()
CLI — Verificar recomendações e comprar Savings Plan
# 1. Obter recomendações de Savings Plans do Cost Explorer (AWS CLI)
aws ce get-savings-plans-purchase-recommendation \
--savings-plans-type COMPUTE_SP \
--term-in-years ONE_YEAR \
--payment-option NO_UPFRONT \
--lookback-period-in-days THIRTY_DAYS \
--query 'SavingsPlansPurchaseRecommendation.{
Summary:SavingsPlansPurchaseRecommendationSummary,
Details:SavingsPlansPurchaseRecommendationDetails[0:3]
}'
# 2. Ver utilização atual de Savings Plans existentes
aws ce get-savings-plans-utilization \
--time-period '{"Start":"2026-06-01","End":"2026-06-30"}' \
--query 'Total.{
Utilized:Utilization.UtilizationPercentage,
UnusedHours:Savings.NetSavings,
TotalCommitment:Utilization.TotalCommitment
}'
# 3. Ver cobertura de Savings Plans (% do On-Demand coberto)
aws ce get-savings-plans-coverage \
--time-period '{"Start":"2026-06-01","End":"2026-06-30"}' \
--granularity MONTHLY \
--query 'SavingsPlansCoverages[*].Coverage.{
CoverageHoursPercentage:CoverageHoursPercentage,
SpendCoveredBySavingsPlans:SpendCoveredBySavingsPlans,
OnDemandCost:OnDemandCost
}'
# 4. Comprar Savings Plan (CUIDADO — compromisso irrevogável)
# Sempre verificar recomendação do Cost Explorer antes
aws savingsplans create-savings-plan \
--savings-plan-offering-id "offering-id-from-describe" \
--commitment 1.00 \
--purchase-time "2026-07-01T00:00:00Z" \
--client-token "unique-idempotency-key-$(uuidgen)"
# 5. Listar Savings Plans ativos
aws savingsplans describe-savings-plans \
--states ACTIVE \
--query 'savingsPlans[*].{
Id:savingsPlanId,
Type:savingsPlanType,
Commitment:commitment,
Start:start,
End:end,
State:state,
PaymentOption:paymentOption,
Term:termDurationInSeconds
}'
# 6. Ver recomendações de Reserved Instances
aws ce get-reservation-purchase-recommendation \
--service "Amazon EC2" \
--lookback-period-in-days THIRTY_DAYS \
--term-in-years ONE_YEAR \
--payment-option NO_UPFRONT \
--query 'Recommendations[0:3].{
Summary:RecommendationSummary,
Details:RecommendationDetails[0:2]
}'
# 7. Ver utilização de Reserved Instances
aws ce get-reservation-utilization \
--time-period '{"Start":"2026-06-01","End":"2026-06-30"}' \
--query 'Total.UtilizationsByTime[*].{
UtilizationPct:Utilization.UtilizationPercentage,
UnusedHours:Utilization.UnusedHours
}'
Armadilhas comuns
1. Over-commitment: comprometer a média, não o baseline
[CONSENSO] A armadilha mais comum em FinOps é comprar Savings Plans ou RIs baseando-se no uso médio dos últimos 30 dias, sem considerar sazonalidade. Um workload com pico de 100 instâncias no Black Friday e mínimo de 20 instâncias em julho deve comprometer apenas as 20 instâncias de baseline — não a média. Over-commitment desperdiça capital em capacidade ociosa.
2. Savings Plans não fornecem capacity reservation
[FATO] Ao contrário de Reserved Instances zonais, Savings Plans não garantem que a capacidade estará disponível. Em cenários de escassez regional (ex: durante eventos de grande escala ou outages), On-Demand e Savings Plans concorrem pela capacidade disponível. Para cargas críticas com SLA de disponibilidade, combine Savings Plans com On-Demand Capacity Reservation (ODCR).
3. Savings Plans não cobrem Spot usage
[FATO] Savings Plans e RIs são aplicados apenas ao uso On-Demand e ODCR. Horas Spot não recebem desconto adicional de Savings Plans — elas já têm seu próprio preço com desconto. Planejar cobertura de Savings Plans sobre workloads que você pretende mover para Spot resulta em compromisso desnecessário.
4. Convertible RIs exigem exchange manual — não são automáticas
[FATO] Ao contrário de EC2 Instance Savings Plans (que se aplicam automaticamente a qualquer tamanho na família), Convertible RIs requerem que você execute manualmente o exchange via console ou API quando quer mudar família, tamanho ou OS. Esquecer de fazer o exchange significa que a RI antiga continua sem ser utilizada enquanto você paga On-Demand pelas novas instâncias.
5. Standard RI zonal: size flexibility ausente
[FATO] Standard RIs com escopo Zonal não têm size flexibility — o desconto só se aplica exatamente ao tamanho, OS e tenancy especificados na compra. RIs com escopo Regional têm size flexibility dentro da família. Para obter flexibilidade de tamanho com RI, sempre use escopo Regional.
6. Savings Plans são aplicados sequencialmente, não em paralelo
[FATO] Se você tem múltiplos Savings Plans (ex: EC2 Instance SP e Compute SP), o X-Ray aplica primeiro o EC2 Instance SP (mais específico), depois o Compute SP para o restante. Comprar ambos sem analisar a sobreposição pode resultar em cobertura redundante pagando pelo Compute SP sem aproveitá-lo.
Exercício de reflexão
Sua empresa tem o seguinte perfil de uso EC2 em us-east-1 (dados dos últimos 90 dias):
- Instâncias estáveis: 20 x
m5.2xlargeLinux rodando 100% do tempo (aplicação web) - Instâncias de processamento: 10 x
c5.4xlargeLinux rodando em média 60% do tempo, com mínimo de 40% e máximo de 90% (jobs diurnos) - Instâncias de ML: 3 x
p3.2xlargeLinux rodando em média 30% do tempo (treinamento semanal)
Responda:
-
Para as instâncias estáveis, qual a diferença financeira anual entre Compute Savings Plans 1 ano All Upfront (desconto ~60%) e Standard RI 1 ano All Upfront (desconto ~64%), considerando
m5.2xlargeOn-Demand a $0.384/hora? Quando a flexibilidade do Compute SP justifica a diferença de desconto? -
Para as instâncias de processamento, qual seria o commitment seguro de Savings Plans considerando o risco de over-commitment? Justifique usando o conceito de P10 (percentil 10 de utilização = 40%).
-
Para as instâncias de ML (
p3.2xlarge, 30% de utilização média): o break-even de Compute SP (desconto ~60%) justifica o compromisso? Qual seria a alternativa mais adequada para esse tipo de workload?
Recursos para aprofundar
- [FATO] Savings Plans types (Compute, EC2 Instance, Database, SageMaker): https://docs.aws.amazon.com/savingsplans/latest/userguide/plan-types.html
- [FATO] Compute Savings Plans vs Reserved Instances (tabela comparativa): https://docs.aws.amazon.com/savingsplans/latest/userguide/sp-ris.html
- [FATO] How Savings Plans apply to usage: https://docs.aws.amazon.com/savingsplans/latest/userguide/sp-applying.html
- [FATO] Reserved Instances for EC2 (escopo regional vs zonal, Standard vs Convertible): https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-reserved-instances.html
- [INCERTO] AWS Pricing Calculator (preços atuais — verificar antes de comprometer): https://calculator.aws/pricing/2/home