Em qualquer sistema de produção, a camada de dados é simultaneamente a mais crítica e a mais difícil de recuperar quando algo dá errado. Um servidor de aplicação com problema pode ser substituído em segundos — um banco de dados com dados corrompidos ou perdidos pode representar danos irreversíveis ao negócio.
A AWS oferece serviços gerenciados que transferem para a infraestrutura da nuvem as responsabilidades mais complexas do gerenciamento de dados: backups automáticos, replicação entre zonas de disponibilidade, failover automático, patching de segurança e scaling de storage. O time de engenharia mantém o controle sobre a configuração, os dados e o schema — a AWS cuida do hardware, do sistema operacional e do software de banco de dados.
Este artigo aprofunda o RDS para bancos de dados relacionais, o ElastiCache para caching distribuído e as estratégias de backup e recuperação de desastre que garantem durabilidade e disponibilidade dos dados em produção.
RDS em Alta Disponibilidade
Multi-AZ: Failover Automático Transparente
O modo Multi-AZ do RDS mantém uma réplica síncrona da instância primária em uma zona de disponibilidade diferente. Em caso de falha da instância primária — hardware, rede, zona de disponibilidade inteira — o RDS promove a réplica automaticamente em 60 a 120 segundos, sem intervenção manual e sem alteração no endpoint de conexão.
A réplica Multi-AZ não serve leituras em condições normais — é exclusivamente uma réplica de standby para failover. Para escalar leituras, são usadas Read Replicas.
# rds-producao.tf
resource "aws_db_instance" "principal" {
identifier = "${var.project_name}-${var.environment}-primary"
# Motor e versão
engine = "postgres"
engine_version = "16.1"
instance_class = "db.r6g.xlarge"
# Storage com auto-scaling
allocated_storage = 100
max_allocated_storage = 1000
storage_type = "gp3"
storage_encrypted = true
kms_key_id = aws_kms_key.rds.arn
# Credenciais gerenciadas via Secrets Manager
manage_master_user_password = true
master_username = "postgres_admin"
master_user_secret_kms_key_id = aws_kms_key.rds.arn
# Alta disponibilidade
multi_az = true
db_subnet_group_name = aws_db_subnet_group.principal.name
vpc_security_group_ids = [aws_security_group.rds.id]
publicly_accessible = false
# Parâmetros de banco
db_name = var.db_name
parameter_group_name = aws_db_parameter_group.postgres16.name
option_group_name = aws_db_option_group.postgres16.name
# Backups e manutenção
backup_retention_period = 14
backup_window = "02:00-03:00"
maintenance_window = "Mon:03:00-Mon:04:00"
auto_minor_version_upgrade = true
allow_major_version_upgrade = false
copy_tags_to_snapshot = true
deletion_protection = true
skip_final_snapshot = false
final_snapshot_identifier = "${var.project_name}-${var.environment}-final"
delete_automated_backups = false
# Monitoramento avançado
monitoring_interval = 60
monitoring_role_arn = aws_iam_role.rds_monitoring.arn
performance_insights_enabled = true
performance_insights_retention_period = 7
performance_insights_kms_key_id = aws_kms_key.rds.arn
enabled_cloudwatch_logs_exports = ["postgresql", "upgrade"]
tags = local.tags_comuns
}
# Read Replica para leituras intensivas
resource "aws_db_instance" "replica_leitura" {
identifier = "${var.project_name}-${var.environment}-replica"
replicate_source_db = aws_db_instance.principal.identifier
instance_class = "db.r6g.large"
publicly_accessible = false
vpc_security_group_ids = [aws_security_group.rds.id]
parameter_group_name = aws_db_parameter_group.postgres16.name
# Réplicas não têm backups próprios — são recuperadas da primária
backup_retention_period = 0
skip_final_snapshot = true
deletion_protection = false
# Promoção automática em caso de falha da primária
# (requer configuração adicional na aplicação)
auto_minor_version_upgrade = true
performance_insights_enabled = true
tags = merge(local.tags_comuns, {
Role = "read-replica"
})
}
# Grupo de parâmetros otimizados para produção
resource "aws_db_parameter_group" "postgres16" {
name = "${var.project_name}-${var.environment}-pg16"
family = "postgres16"
# Configurações de performance
parameter {
name = "shared_buffers"
value = "{DBInstanceClassMemory/4096}"
}
parameter {
name = "effective_cache_size"
value = "{DBInstanceClassMemory*3/4096}"
}
parameter {
name = "work_mem"
value = "16384" # 16MB por operação de sort
}
parameter {
name = "maintenance_work_mem"
value = "524288" # 512MB para operações de vacuum
}
# Configurações de logging
parameter {
name = "log_min_duration_statement"
value = "1000" # loga queries > 1s
}
parameter {
name = "log_checkpoints"
value = "1"
}
parameter {
name = "log_lock_waits"
value = "1"
}
parameter {
name = "log_temp_files"
value = "0" # loga todos os arquivos temporários
}
# Configurações de conexão
parameter {
name = "max_connections"
value = "200"
}
# WAL e replicação
parameter {
name = "wal_level"
value = "replica"
apply_method = "pending-reboot"
}
parameter {
name = "max_wal_senders"
value = "5"
apply_method = "pending-reboot"
}
lifecycle {
create_before_destroy = true
}
}
# Chave KMS para criptografia do RDS
resource "aws_kms_key" "rds" {
description = "Chave KMS para criptografia do RDS"
deletion_window_in_days = 7
enable_key_rotation = true
tags = local.tags_comuns
}
resource "aws_kms_alias" "rds" {
name = "alias/${var.project_name}-${var.environment}-rds"
target_key_id = aws_kms_key.rds.key_id
}
RDS Proxy: Gerenciamento de Conexões para Aplicações de Alta Escala
Bancos de dados PostgreSQL têm um limite prático de conexões simultâneas — cada conexão consome memória significativa. Aplicações com muitas instâncias ou funções Lambda que abrem conexões novas a cada invocação podem rapidamente esgotar o pool de conexões disponíveis.
O RDS Proxy é um proxy gerenciado que mantém um pool de conexões persistentes ao banco e distribui as conexões das aplicações entre elas. Para funções Lambda especialmente, o Proxy é praticamente obrigatório em produção:
# RDS Proxy para gerenciamento de pool de conexões
resource "aws_db_proxy" "principal" {
name = "${var.project_name}-${var.environment}-proxy"
debug_logging = false
engine_family = "POSTGRESQL"
idle_client_timeout = 1800
require_tls = true
role_arn = aws_iam_role.rds_proxy.arn
vpc_security_group_ids = [aws_security_group.rds_proxy.id]
vpc_subnet_ids = module.vpc.ids_subnets_privadas
auth {
auth_scheme = "SECRETS"
description = "Credenciais do banco de dados"
iam_auth = "REQUIRED"
secret_arn = aws_db_instance.principal.master_user_secret[0].secret_arn
}
tags = local.tags_comuns
}
resource "aws_db_proxy_default_target_group" "principal" {
db_proxy_name = aws_db_proxy.principal.name
connection_pool_config {
connection_borrow_timeout = 120
max_connections_percent = 90
max_idle_connections_percent = 50
}
}
resource "aws_db_proxy_target" "principal" {
db_instance_identifier = aws_db_instance.principal.identifier
db_proxy_name = aws_db_proxy.principal.name
target_group_name = aws_db_proxy_default_target_group.principal.name
}
ElastiCache: Caching Distribuído com Redis
O ElastiCache oferece Redis e Memcached como serviços gerenciados. Redis é a escolha dominante por sua versatilidade — suporta estruturas de dados complexas, pub/sub, streams, scripting Lua e persistência opcional.
Cluster Redis com Replicação
# elasticache.tf
# Subnet group para o ElastiCache
resource "aws_elasticache_subnet_group" "redis" {
name = "${var.project_name}-${var.environment}-redis-subnet"
subnet_ids = module.vpc.ids_subnets_privadas
tags = local.tags_comuns
}
# Grupo de parâmetros Redis
resource "aws_elasticache_parameter_group" "redis7" {
name = "${var.project_name}-${var.environment}-redis7"
family = "redis7"
# Habilita notificações de keyspace — útil para implementar
# invalidação de cache orientada a eventos
parameter {
name = "notify-keyspace-events"
value = "Ex" # E=keyspace events, x=expired events
}
# Desabilita comandos perigosos em produção
parameter {
name = "rename-commands"
value = "FLUSHALL banned FLUSHDB banned CONFIG banned"
}
tags = local.tags_comuns
}
# Cluster Redis com replicação e failover automático
resource "aws_elasticache_replication_group" "redis" {
replication_group_id = "${var.project_name}-${var.environment}-redis"
description = "Cluster Redis para ${var.project_name} ${var.environment}"
node_type = var.redis_node_type
num_cache_clusters = var.environment == "production" ? 3 : 1
port = 6379
parameter_group_name = aws_elasticache_parameter_group.redis7.name
subnet_group_name = aws_elasticache_subnet_group.redis.name
security_group_ids = [aws_security_group.redis.id]
# Alta disponibilidade
automatic_failover_enabled = var.environment == "production"
multi_az_enabled = var.environment == "production"
at_rest_encryption_enabled = true
transit_encryption_enabled = true
auth_token = var.redis_auth_token
auth_token_update_strategy = "ROTATE"
# Versão Redis
engine_version = "7.1"
# Manutenção e backups
maintenance_window = "tue:03:00-tue:04:00"
snapshot_window = "02:00-03:00"
snapshot_retention_limit = 7
auto_minor_version_upgrade = true
# Logs para CloudWatch
log_delivery_configuration {
destination = aws_cloudwatch_log_group.redis_slow.name
destination_type = "cloudwatch-logs"
log_format = "json"
log_type = "slow-log"
}
log_delivery_configuration {
destination = aws_cloudwatch_log_group.redis_engine.name
destination_type = "cloudwatch-logs"
log_format = "json"
log_type = "engine-log"
}
tags = local.tags_comuns
}
resource "aws_cloudwatch_log_group" "redis_slow" {
name = "/elasticache/${var.project_name}-${var.environment}/slow-log"
retention_in_days = 14
}
resource "aws_cloudwatch_log_group" "redis_engine" {
name = "/elasticache/${var.project_name}-${var.environment}/engine-log"
retention_in_days = 7
}
Padrões de Caching na Aplicação
Com a infraestrutura do Redis provisionada, a aplicação implementa os padrões de caching que reduzem a carga no banco de dados:
// src/cache/redis.client.js
const { createClient } = require('redis');
let client = null;
async function getClient() {
if (client?.isReady) return client;
client = createClient({
url: process.env.REDIS_URL,
socket: {
tls: true,
rejectUnauthorized: true,
connectTimeout: 5000,
},
password: process.env.REDIS_AUTH_TOKEN,
});
client.on('error', (err) => {
console.error(JSON.stringify({ level: 'error', msg: 'Redis error', err: err.message }));
});
client.on('reconnecting', () => {
console.warn(JSON.stringify({ level: 'warn', msg: 'Redis reconnecting' }));
});
await client.connect();
return client;
}
module.exports = { getClient };
// src/cache/cache.service.js
const { getClient } = require('./redis.client');
const PREFIXO = process.env.SERVICE_NAME || 'api';
const TTL_PADRAO = 300; // 5 minutos
class CacheService {
// ── Cache-Aside (Lazy Loading) ────────────────────
// Busca no cache; se não encontrar, busca na fonte e armazena
async getOuBuscar(chave, funcaoBusca, ttl = TTL_PADRAO) {
const redis = await getClient();
const chaveCompleta = `${PREFIXO}:${chave}`;
// Tenta buscar no cache
const cached = await redis.get(chaveCompleta);
if (cached) {
return JSON.parse(cached);
}
// Cache miss — busca na fonte de dados
const dados = await funcaoBusca();
// Armazena no cache para próximas requisições
await redis.setEx(
chaveCompleta,
ttl,
JSON.stringify(dados)
);
return dados;
}
// ── Invalidação por chave específica ──────────────
async invalidar(chave) {
const redis = await getClient();
await redis.del(`${PREFIXO}:${chave}`);
}
// ── Invalidação por padrão ────────────────────────
// Útil para invalidar todos os caches relacionados a uma entidade
async invalidarPadrao(padrao) {
const redis = await getClient();
const chaves = await redis.keys(`${PREFIXO}:${padrao}`);
if (chaves.length > 0) {
// Usa pipeline para deletar múltiplas chaves atomicamente
const pipeline = redis.multi();
chaves.forEach(chave => pipeline.del(chave));
await pipeline.exec();
}
return chaves.length;
}
// ── Write-Through Cache ───────────────────────────
// Atualiza cache e banco de dados simultaneamente
async escreverComCache(chave, dados, funcaoEscrita, ttl = TTL_PADRAO) {
const redis = await getClient();
const chaveCompleta = `${PREFIXO}:${chave}`;
// Executa as operações em paralelo
await Promise.all([
funcaoEscrita(dados),
redis.setEx(chaveCompleta, ttl, JSON.stringify(dados))
]);
return dados;
}
// ── Rate Limiting com Redis ───────────────────────
async verificarRateLimit(identificador, limite, janelaSegundos) {
const redis = await getClient();
const chave = `${PREFIXO}:rate:${identificador}`;
// Script Lua garante atomicidade
const script = `
local atual = redis.call('INCR', KEYS[1])
if atual == 1 then
redis.call('EXPIRE', KEYS[1], ARGV[2])
end
return { atual, redis.call('TTL', KEYS[1]) }
`;
const [contagem, ttl] = await redis.eval(
script,
{ keys: [chave], arguments: [limite.toString(), janelaSegundos.toString()] }
);
return {
permitido: contagem <= limite,
contagem: parseInt(contagem),
limite,
resetEm: parseInt(ttl),
};
}
// ── Distributed Lock ─────────────────────────────
// Evita processamento duplicado em sistemas distribuídos
async adquirirLock(recurso, ttlMs = 30000) {
const redis = await getClient();
const chave = `${PREFIXO}:lock:${recurso}`;
const token = `${Date.now()}-${Math.random()}`;
// SET NX (only if Not eXists) com expiração
const adquirido = await redis.set(chave, token, {
NX: true,
PX: ttlMs,
});
if (!adquirido) {
return null; // Lock não adquirido
}
// Retorna função para liberar o lock
return async () => {
// Script Lua garante que apenas quem adquiriu pode liberar
const scriptLiberar = `
if redis.call('GET', KEYS[1]) == ARGV[1] then
return redis.call('DEL', KEYS[1])
else
return 0
end
`;
await redis.eval(scriptLiberar, { keys: [chave], arguments: [token] });
};
}
}
module.exports = new CacheService();
Uso do serviço de cache na camada de repositório:
// src/repositories/produto.repository.js
const cache = require('../cache/cache.service');
const db = require('../database/db');
class ProdutoRepository {
async buscarPorId(id) {
return cache.getOuBuscar(
`produto:${id}`,
() => db.query('SELECT * FROM produtos WHERE id = $1', [id])
.then(result => result.rows[0]),
600 // 10 minutos
);
}
async buscarCategoria(categoriaId) {
return cache.getOuBuscar(
`categoria:${categoriaId}:produtos`,
() => db.query(
'SELECT * FROM produtos WHERE categoria_id = $1 AND ativo = true ORDER BY nome',
[categoriaId]
).then(result => result.rows),
300 // 5 minutos
);
}
async atualizar(id, dados) {
const produto = await db.query(
'UPDATE produtos SET nome = $1, preco = $2, updated_at = NOW() WHERE id = $3 RETURNING *',
[dados.nome, dados.preco, id]
).then(result => result.rows[0]);
// Invalida o cache do produto e da categoria
await Promise.all([
cache.invalidar(`produto:${id}`),
cache.invalidarPadrao(`categoria:${produto.categoria_id}:*`),
]);
return produto;
}
}
module.exports = new ProdutoRepository();
Estratégias de Backup e Recuperação de Desastre
Os Objetivos de Recuperação: RPO e RTO
Toda estratégia de dados começa com dois números que definem o que é aceitável perder e quanto tempo de indisponibilidade é tolerável:
RPO — Recovery Point Objective — o máximo de dados que pode ser perdido em caso de desastre. Se o RPO é de 1 hora, a organização aceita perder até 1 hora de transações. Se o RPO é de zero, nenhuma transação pode ser perdida — o que exige replicação síncrona.
RTO — Recovery Time Objective — o máximo de tempo que o sistema pode ficar indisponível antes de ser restaurado. Se o RTO é de 15 minutos, o sistema deve estar operacional em no máximo 15 minutos após uma falha.
RPO e RTO mais agressivos custam mais — em infraestrutura, em complexidade operacional e em custos de engenharia. A definição desses objetivos é uma decisão de negócio, não apenas técnica.
Hierarquia de Backup do RDS
O RDS oferece três níveis de proteção de dados que trabalham em camadas:
Backups automáticos — o RDS faz snapshots diários do volume de storage e retém os logs de transação (WAL) para permitir recuperação point-in-time. A janela de retenção é configurável de 1 a 35 dias. Permitem restaurar para qualquer segundo dentro da janela de retenção.
Snapshots manuais — criados explicitamente e retidos indefinidamente até serem deletados manualmente. Adequados para pontos de checkpoint antes de operações arriscadas — migrations, atualizações de versão, mudanças de schema.
Backups cross-region — réplicas de snapshots em outra região para proteção contra falha regional completa. Essencial para RPO baixo em cenários de disaster recovery.
# Operações de backup e restauração via AWS CLI
# Cria snapshot manual antes de uma migration
aws rds create-db-snapshot \
--db-instance-identifier minha-api-production-db \
--db-snapshot-identifier pre-migration-$(date +%Y%m%d-%H%M%S) \
--tags Key=Motivo,Value=pre-migration Key=Autor,Value=joao
# Lista snapshots disponíveis
aws rds describe-db-snapshots \
--db-instance-identifier minha-api-production-db \
--query 'DBSnapshots[*].{ID:DBSnapshotIdentifier,Status:Status,Criado:SnapshotCreateTime}' \
--output table
# Restaura para um ponto específico no tempo (point-in-time recovery)
aws rds restore-db-instance-to-point-in-time \
--source-db-instance-identifier minha-api-production-db \
--target-db-instance-identifier minha-api-recovery-test \
--restore-time 2025-03-10T14:30:00Z \
--db-instance-class db.r6g.large \
--no-multi-az \
--db-subnet-group-name minha-api-staging-db-subnet-group \
--vpc-security-group-ids sg-0abc123
# Copia snapshot para outra região (cross-region backup)
aws rds copy-db-snapshot \
--source-db-snapshot-identifier \
arn:aws:rds:us-east-1:123456789:snapshot:pre-migration-20250310 \
--target-db-snapshot-identifier pre-migration-20250310-dr \
--source-region us-east-1 \
--region us-west-2 \
--kms-key-id arn:aws:kms:us-west-2:123456789:key/abc-def
Automatizando Backups com AWS Backup
O AWS Backup é um serviço centralizado que gerencia backups de múltiplos serviços AWS — RDS, EBS, EFS, DynamoDB, S3 — com uma única política:
# aws-backup.tf
resource "aws_backup_vault" "principal" {
name = "${var.project_name}-${var.environment}-vault"
kms_key_arn = aws_kms_key.backup.arn
tags = local.tags_comuns
}
# Vault de destino para cross-region replication
resource "aws_backup_vault" "dr_region" {
provider = aws.dr_region
name = "${var.project_name}-${var.environment}-vault-dr"
kms_key_arn = aws_kms_key.backup_dr.arn
}
resource "aws_backup_plan" "producao" {
name = "${var.project_name}-${var.environment}-backup-plan"
rule {
rule_name = "backup-diario"
target_vault_name = aws_backup_vault.principal.name
schedule = "cron(0 2 * * ? *)" # Todo dia às 2h UTC
start_window_minutes = 60
completion_window_minutes = 180
recovery_point_tags = local.tags_comuns
lifecycle {
cold_storage_after = 30 # Move para Glacier após 30 dias
delete_after = 90 # Deleta após 90 dias
}
# Replica backup para outra região
copy_action {
destination_vault_arn = aws_backup_vault.dr_region.arn
lifecycle {
delete_after = 30 # Mantém DR por 30 dias
}
}
}
rule {
rule_name = "backup-semanal"
target_vault_name = aws_backup_vault.principal.name
schedule = "cron(0 3 ? * SUN *)" # Todo domingo às 3h UTC
lifecycle {
delete_after = 365 # Retém backups semanais por 1 ano
}
}
tags = local.tags_comuns
}
# Associa o plano de backup ao RDS e outros recursos
resource "aws_backup_selection" "banco_dados" {
name = "banco-dados-producao"
iam_role_arn = aws_iam_role.backup.arn
plan_id = aws_backup_plan.producao.id
resources = [
aws_db_instance.principal.arn,
aws_elasticache_replication_group.redis.arn,
]
condition {
string_equals {
key = "aws:ResourceTag/Environment"
value = "production"
}
}
}
Testando a Recuperação
Uma estratégia de backup sem testes regulares de recuperação é uma falsa segurança. O processo de testar a recuperação deve ser automatizado e executado regularmente:
#!/bin/bash
# scripts/testar-recuperacao.sh
# Testa a capacidade de recuperação do banco de dados a partir de um snapshot
# Deve ser executado mensalmente via pipeline de CI/CD
set -euo pipefail
SNAPSHOT_ID="$1"
AMBIENTE_TESTE="recovery-test-$(date +%Y%m%d)"
REGIAO="us-east-1"
log() { echo "[$(date -u +%H:%M:%S)] $*"; }
erro() { echo "[$(date -u +%H:%M:%S)] ERRO: $*" >&2; exit 1; }
log "=== Iniciando teste de recuperação ==="
log "Snapshot: $SNAPSHOT_ID"
log "Ambiente de teste: $AMBIENTE_TESTE"
# Restaura o banco de dados a partir do snapshot
log "Restaurando banco de dados..."
aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier "$AMBIENTE_TESTE" \
--db-snapshot-identifier "$SNAPSHOT_ID" \
--db-instance-class "db.t3.micro" \
--no-multi-az \
--no-publicly-accessible \
--db-subnet-group-name "minha-api-staging-db-subnet-group" \
--vpc-security-group-ids "sg-0abc123" \
--region "$REGIAO"
# Aguarda o banco ficar disponível
log "Aguardando banco ficar disponível..."
aws rds wait db-instance-available \
--db-instance-identifier "$AMBIENTE_TESTE" \
--region "$REGIAO"
log "Banco disponível. Executando verificações..."
# Obtém o endpoint do banco restaurado
ENDPOINT=$(aws rds describe-db-instances \
--db-instance-identifier "$AMBIENTE_TESTE" \
--query 'DBInstances[0].Endpoint.Address' \
--output text \
--region "$REGIAO")
# Executa verificações de integridade
RESULTADO=$(psql \
"postgresql://postgres_admin:$DB_PASSWORD@$ENDPOINT:5432/producao" \
-c "SELECT COUNT(*) FROM usuarios;" \
-t -A)
if [ -z "$RESULTADO" ] || [ "$RESULTADO" -eq 0 ]; then
erro "Verificação falhou: tabela usuarios vazia ou inacessível"
fi
log "Verificação bem-sucedida: $RESULTADO usuários encontrados"
# Verifica integridade referencial
psql "postgresql://postgres_admin:$DB_PASSWORD@$ENDPOINT:5432/producao" \
-c "SELECT COUNT(*) FROM pedidos p LEFT JOIN usuarios u ON p.usuario_id = u.id WHERE u.id IS NULL;" \
-t -A | {
read ORFAOS
if [ "$ORFAOS" -gt 0 ]; then
log "AVISO: $ORFAOS pedidos órfãos encontrados — possível problema de integridade"
else
log "Integridade referencial: OK"
fi
}
# Registra o resultado do teste
aws cloudwatch put-metric-data \
--namespace "BackupTests" \
--metric-name "RecoveryTestSuccess" \
--value 1 \
--dimensions "Environment=production" \
--region "$REGIAO"
log "=== Teste de recuperação concluído com sucesso ==="
# Limpa o banco de teste
log "Removendo banco de teste..."
aws rds delete-db-instance \
--db-instance-identifier "$AMBIENTE_TESTE" \
--skip-final-snapshot \
--region "$REGIAO"
log "Banco de teste removido."
Monitoramento da Camada de Dados
Alertas Essenciais para RDS e ElastiCache
# observabilidade/prometheus/rules/alertas-dados.yml
groups:
- name: rds
rules:
- alert: RDSAltaCPU
expr: aws_rds_cpuutilization_average > 80
for: 10m
labels:
severity: warning
annotations:
summary: "CPU do RDS acima de 80%"
description: |
Uso de CPU: {{ $value }}%
Considerar: otimização de queries, upgrade de instância
ou adicionar read replica para distribuir carga.
- alert: RDSConexoesProximasDoLimite
expr: |
aws_rds_database_connections_average
/
aws_rds_database_connections_average offset 0s * 0 + 200
> 0.85
for: 5m
labels:
severity: critical
annotations:
summary: "Conexões RDS acima de 85% do máximo"
runbook_url: "https://wiki.empresa.com/runbooks/conexoes-rds"
- alert: RDSStorageAbaixo20Percent
expr: |
aws_rds_free_storage_space_average
/
aws_rds_allocated_storage_average
< 0.20
for: 30m
labels:
severity: warning
annotations:
summary: "Storage do RDS com menos de 20% livre"
description: "Storage livre: {{ $value | humanizePercentage }}"
- name: elasticache
rules:
- alert: RedisBaixaMemoriaDisponivel
expr: |
aws_elasticache_freeable_memory_average
/
aws_elasticache_bytes_used_for_cache_average
< 0.10
for: 5m
labels:
severity: critical
annotations:
summary: "Redis com menos de 10% de memória livre"
description: |
O Redis está próximo da capacidade máxima.
Risco de eviction de chaves e degradação de performance.
- alert: RedisCacheHitRateBaixa
expr: |
aws_elasticache_cache_hits_average
/
(aws_elasticache_cache_hits_average + aws_elasticache_cache_misses_average)
< 0.80
for: 15m
labels:
severity: warning
annotations:
summary: "Cache hit rate do Redis abaixo de 80%"
description: |
Cache hit rate atual: {{ $value | humanizePercentage }}
Hit rate baixo aumenta a carga no banco de dados.
O Que Vem a Seguir
O próximo artigo completa o que vimos com os serviços de rede e entrega de conteúdo da AWS — Route53 para DNS, CloudFront para CDN e ACM para certificados SSL/TLS — os componentes que ficam entre os usuários e a aplicação.
Referências para Aprofundamento
Documentação oficial AWS - Amazon RDS Documentation — docs.aws.amazon.com — Documentação completa do RDS, incluindo guias de Multi-AZ, Read Replicas, RDS Proxy e boas práticas de performance. - Amazon ElastiCache for Redis — docs.aws.amazon.com — Documentação do ElastiCache para Redis, cobrindo clustering, replicação, configuração de parâmetros e monitoramento. - AWS Backup Documentation — docs.aws.amazon.com — Guia completo do AWS Backup, incluindo planos de backup, vaults e replicação cross-region.
Performance e otimização - RDS Performance Insights — docs.aws.amazon.com — Documentação do Performance Insights com guia de interpretação dos dados e identificação de gargalos. - Redis Best Practices — redis.io — Documentação oficial do Redis com padrões de uso, incluindo caching, rate limiting, pub/sub e distributed locks.
Disaster Recovery - AWS Disaster Recovery Whitepaper — docs.aws.amazon.com — Whitepaper oficial da AWS sobre estratégias de disaster recovery, definindo os padrões Backup & Restore, Pilot Light, Warm Standby e Multi-Site Active/Active.