Metodologia8 min

Traduzindo Usuários em Carga: a matemática por trás dos testes

Quantos requests por segundo representam 1000 usuários? Aprenda a traduzir métricas de negócio em carga técnica realista.

"Precisamos aguentar 100.000 usuários simultâneos." Parece claro, mas o que isso significa tecnicamente? Quantos requests por segundo? Quantas conexões? Quanto de CPU? A tradução de métricas de negócio para carga técnica é uma das habilidades mais importantes — e mais mal executadas — em performance engineering.

Usuários simultâneos é métrica de negócio. Requests por segundo é métrica técnica. Saber traduzir entre elas é essencial.

O Problema da Tradução

Ambiguidade de "usuários"

O que "100K usuários" pode significar:

1. Usuários registrados: 100K contas
   → Relevância para carga: zero

2. Usuários ativos/mês (MAU): 100K
   → Talvez 10% online em pico

3. Usuários ativos/dia (DAU): 100K
   → Talvez 20% online em pico

4. Usuários simultâneos: 100K
   → Conectados ao mesmo tempo

5. Usuários fazendo ações: 100K
   → Gerando requests agora

A diferença prática

Cenário: "100K usuários ativos"

Interpretação errada:
  100K usuários × 1 req/s = 100K req/s
  (usuário não faz 1 request por segundo)

Interpretação correta:
  100K usuários online
  ÷ 30s entre ações (think time)
  = 3.333 req/s

Diferença: 30x

Modelo de Carga: Little's Law

A fórmula fundamental

L = λ × W

Onde:
L = Número de requests concorrentes (em processamento)
λ = Taxa de chegada (requests/segundo)
W = Tempo médio de processamento (segundos)

Exemplo:
λ = 100 req/s
W = 0.2s (200ms)
L = 100 × 0.2 = 20 requests simultâneos

Aplicação inversa

Se você sabe:
- Quantos usuários online: U
- Think time médio: T (segundos entre ações)
- Ações por sessão: A

Taxa de requests = U × A / T

Exemplo:
U = 10.000 usuários online
T = 30s think time
A = 1 (uma ação)

Taxa = 10.000 × 1 / 30 = 333 req/s

Modelando Comportamento Real

Funil de conversão

Entrada: 100K visitantes/hora

Funil:
  Home page: 100K (100%)
  Listagem: 70K (70%)
  Produto: 50K (50%)
  Add cart: 10K (10%)
  Checkout: 5K (5%)
  Pagamento: 4K (4%)

Requests por endpoint:
  GET /           : 100K/h = 28 req/s
  GET /products   : 70K/h = 19 req/s
  GET /product/:id: 50K/h = 14 req/s
  POST /cart      : 10K/h = 3 req/s
  GET /checkout   : 5K/h = 1.4 req/s
  POST /payment   : 4K/h = 1.1 req/s

Total: ~66 req/s

Múltiplos requests por página

Página de produto carrega:
  - HTML: 1 request
  - API produto: 1 request
  - API relacionados: 1 request
  - API reviews: 1 request
  - Imagens: 5 requests
  - JS/CSS: 3 requests

Total: 12 requests por page view

Se 50K page views/hora:
  50K × 12 = 600K requests/hora
  = 167 req/s (não 14 req/s!)

Think time realista

Distribuição de think time (segundos):

Ação              | Média | p50 | p95
------------------|-------|-----|-----
Ler página home   | 15    | 10  | 60
Navegar listagem  | 20    | 15  | 90
Analisar produto  | 45    | 30  | 180
Decidir compra    | 60    | 45  | 300
Preencher checkout| 120   | 90  | 400

Não use valores fixos!
Use distribuição (log-normal funciona bem)

Calculadora de Carga

Template de cálculo

## Cálculo de Carga - [Sistema]

### Premissas de Negócio
- Usuários ativos no pico: 50.000
- Sessão média: 10 minutos
- Think time médio: 30 segundos
- Ações por sessão: 20

### Cálculo Base
Taxa de ações = 50.000 / 30 = 1.667 ações/s

### Por Endpoint (baseado em analytics)
| Endpoint | % tráfego | req/s |
|----------|-----------|-------|
| GET /api/products | 40% | 667 |
| GET /api/product/:id | 30% | 500 |
| POST /api/cart | 15% | 250 |
| GET /api/checkout | 10% | 167 |
| POST /api/payment | 5% | 83 |

### Multiplicadores
- Cache misses (30%): +500 req/s ao DB
- Retries (5%): +83 req/s total
- Healthchecks: +10 req/s

### Carga Total Estimada
- API: 1.667 req/s
- DB queries: 2.500 req/s
- Cache ops: 4.000 req/s

### Margem de Segurança (2x)
- Target: 3.334 req/s sustentado
- Pico: 5.000 req/s por 5 minutos

Script de cálculo

def calculate_load(
    active_users: int,
    think_time_seconds: float,
    session_duration_minutes: float,
    pages_per_session: float,
    requests_per_page: float,
    safety_margin: float = 2.0
) -> dict:
    """
    Calcula carga técnica a partir de métricas de negócio
    """
    # Taxa base de page views
    page_views_per_second = active_users / think_time_seconds

    # Taxa de requests (incluindo assets, APIs, etc)
    requests_per_second = page_views_per_second * requests_per_page

    # Concurrent requests (Little's Law)
    avg_response_time = 0.2  # assumindo 200ms
    concurrent_requests = requests_per_second * avg_response_time

    return {
        "page_views_per_second": round(page_views_per_second, 1),
        "requests_per_second": round(requests_per_second, 1),
        "concurrent_requests": round(concurrent_requests, 1),
        "target_with_margin": round(requests_per_second * safety_margin, 1),
        "peak_capacity": round(requests_per_second * safety_margin * 1.5, 1)
    }

# Exemplo
result = calculate_load(
    active_users=50000,
    think_time_seconds=30,
    session_duration_minutes=10,
    pages_per_session=20,
    requests_per_page=8
)

print(result)
# {
#   'page_views_per_second': 1666.7,
#   'requests_per_second': 13333.3,
#   'concurrent_requests': 2666.7,
#   'target_with_margin': 26666.7,
#   'peak_capacity': 40000.0
# }

Validando o Modelo

Comparar com produção

-- Pico de requests por segundo
SELECT
  date_trunc('minute', timestamp) as minute,
  count(*) / 60.0 as rps
FROM access_logs
WHERE timestamp > now() - interval '7 days'
GROUP BY 1
ORDER BY rps DESC
LIMIT 10;

-- Pico de usuários únicos por minuto
SELECT
  date_trunc('minute', timestamp) as minute,
  count(distinct user_id) as unique_users
FROM access_logs
WHERE timestamp > now() - interval '7 days'
GROUP BY 1
ORDER BY unique_users DESC
LIMIT 10;

Calcular ratio real

-- Requests por usuário ativo
WITH hourly AS (
  SELECT
    date_trunc('hour', timestamp) as hour,
    count(*) as requests,
    count(distinct user_id) as users
  FROM access_logs
  WHERE timestamp > now() - interval '7 days'
  GROUP BY 1
)
SELECT
  avg(requests::float / nullif(users, 0)) as req_per_user_hour,
  avg(requests::float / nullif(users, 0) / 3600) as req_per_user_second
FROM hourly;

Armadilhas Comuns

1. Ignorar o funil

❌ "100K usuários × 10 req/s = 1M req/s"

✅ Modelar o funil:
   100K visualizam home
   30K veem produto
   3K fazem checkout
   → Requests variam por etapa

2. Think time de robô

❌ "Virtual user faz request, espera 1s, faz request"

✅ Think time realista:
   Média 30s, distribuição log-normal
   Varia por tipo de página

3. Esquecer requests internos

❌ "Calculei só requests da API"

✅ Incluir:
   - Service-to-service calls
   - DB queries por request
   - Cache operations
   - Background jobs triggered

4. Pico = Média

❌ "Média de 1000 req/s, vou testar 1000"

✅ Modelar picos:
   Pico pode ser 3-5x a média
   Testar para pico, não média

Exemplo Completo

Cenário: Black Friday

## Planejamento de Capacidade - Black Friday

### Histórico
- Black Friday 2023: 80K usuários pico
- Crescimento projetado: 50%
- Target 2024: 120K usuários pico

### Modelo de Carga

**Usuários ativos no pico**: 120.000

**Distribuição por jornada**:
| Jornada | % | Usuários | Think time | Req/s |
|---------|---|----------|------------|-------|
| Browse | 60% | 72K | 20s | 3.600 |
| Search | 25% | 30K | 15s | 2.000 |
| Checkout | 15% | 18K | 45s | 400 |

**Total base**: 6.000 req/s

**Multiplicadores**:
- Requests por página: ×8 = 48.000 req/s
- Cache miss (40%): +19.200 DB queries/s
- Margin (2x): 96.000 req/s

### Requisitos de Infraestrutura
- API servers: 96K / 2K per instance = 48 instances
- DB connections: 19.2K × 0.1s = 1.920 concurrent
- Cache: 48K × 0.01s = 480 concurrent ops

### Teste de Validação
- Carga sustentada: 50K req/s por 2h
- Pico: 100K req/s por 15min
- Spike: 150K req/s por 1min

Conclusão

Traduzir usuários em carga requer:

  1. Entender o que "usuários" significa no contexto
  2. Modelar o funil de comportamento
  3. Calcular think time realista
  4. Incluir todos os requests (não só API principal)
  5. Validar contra dados reais de produção
  6. Aplicar margem de segurança para picos

O número de usuários é o input. O número de requests é o output. A matemática no meio é o que separa sucesso de fracasso.


Este artigo faz parte da série sobre a metodologia OCTOPUS de Performance Engineering.

OCTOPUSload testingcapacitycálculo
Compartilhar:
Read in English

Quer entender os limites da sua plataforma?

Entre em contato para uma avaliação de performance.

Fale Conosco