AULA 66 MÓDULO 9 tópicos avançados ⏱ 60 min

Design de APIs Escaláveis

Escalabilidade horizontal vs vertical. Stateless para escala. Os 5 princípios: cache, async, paginação, índices, connection pool.

escalabilidadehorizontalstatelesscachepaginação cursorconnection poolload balancer

O que é escalabilidade?

Escalabilidade é a capacidade de aumentar a capacidade de um sistema adicionando recursos. Escalabilidade horizontal (mais instâncias) é preferível à vertical (máquinas maiores) — resiliente a falhas e sem limite teórico de crescimento.

Escalabilidade Vertical
Servidor maior (mais CPU/RAM)
Simples de implementar
Tem limite físico
Ponto único de falha
Escalabilidade Horizontal
Mais instâncias atrás de load balancer
Sem limite teórico
Resiliente a falhas
Requer stateless (JWT/Redis sessões)

Princípio stateless para escala

Para escalar horizontalmente, cada instância deve ser intercambiável. Isso requer que estado seja externalizado — sessões no Redis, arquivos no S3, nada em memória local que precise ser compartilhado.

📋
checklist de statelessness
✓ Sessões no Redis (não memória). ✓ Uploads direto para S3 (não disco local). ✓ Logs para stdout (não arquivo). ✓ Cache no Redis (não memória do processo). ✓ Filas externas (BullMQ/Redis).

Princípios de design escalável

APIs que escalam bem seguem padrões comprovados. Veja os 5 mais importantes:

1. Cache agressivo
Redis para queries custosas. TTL curto para dados dinâmicos, longo para estáticos. Invalide no evento.
2. Async onde possível
Background jobs para tudo que não precisa ser síncrono — emails, relatórios, processamentos.
3. Paginação obrigatória
Nunca retorne todos os registros. Cursor-based para feeds dinâmicos.
4. Índices corretos
Query lenta = usuário esperando = servidor sobrecarregado. EXPLAIN ANALYZE em toda query lenta.
5. Connection pool
N instâncias × M conexões = banco sobrecarregado. Use pgBouncer ou Prisma pool.
javascript
// Padrões de escalabilidade em Express

// 1. Cache com invalidação por evento
const invalidateUserCache = async (userId) => {
  await redis.del(`user:${userId}`)
  await redis.del(`user:${userId}:orders`)
}

// 2. Paginação cursor para feeds
app.get('/feed', async (req, res) => {
  const { after, limit = 20 } = req.query
  const posts = await db.query(`
    SELECT * FROM posts
    WHERE ($1::uuid IS NULL OR id < $1)
    ORDER BY created_at DESC LIMIT $2
  `, [after, +limit + 1])
  const hasMore = posts.length > limit
  if (hasMore) posts.pop()
  res.json({ data: posts, nextCursor: hasMore ? posts.at(-1)?.id : null })
})

// 3. Connection pool configurado
const sql = postgres(process.env.DATABASE_URL, {
  max: 10,      // máx 10 conexões por instância
  idle_timeout: 20,
  connect_timeout: 10
})
quiz · aula 66
Teste seus conhecimentos
0/3 respondidas
QUESTÃO 01
Por que escalabilidade horizontal é preferível à vertical?
QUESTÃO 02
Por que sessões devem ficar no Redis, não na memória do processo?
QUESTÃO 03
O que é connection pooling e por que é importante?
0/3