Bem-vindo
Tudo que o mercado exige que você conheça:
menos confusão, mais clareza.

Antes de decorar verbos HTTP ou schemas GraphQL, você precisa entender o mapa — o que é API, o que é RPC, e como REST, GraphQL e gRPC se encaixam nisso tudo. Esse é o ponto de partida.

Antes de tudo — entenda o mapa
API — o conceito mais amplo

API (Application Programming Interface) é qualquer interface que permite que dois programas se comuniquem. É o "quê": o contrato de como acessar uma funcionalidade. REST, GraphQL e gRPC são todos formas de construir APIs.

RPC — um estilo de comunicação

RPC (Remote Procedure Call) é o "como": a abordagem de chamar funções remotas como se fossem locais. RPC não é uma API — ele implementa uma API. O gRPC usa RPC por baixo para construir APIs de alta performance.

Como eles se relacionam
API Conceito. Qualquer contrato entre programas. REST, GraphQL e gRPC são estilos de API.
RPC Paradigma. "Chame funções remotas como locais." Não é uma API — é um mecanismo para construir APIs.
REST
Estilo arquitetural. Recursos + verbos HTTP. Pensa em dados.
GraphQL
Linguagem de consulta. Cliente define o shape dos dados.
gRPC
Framework RPC moderno. Pensa em ações / funções. Binário, rápido.
A distinção que mais confunde

REST pensa em recursos: GET /pedidos/99 — "me dê o pedido 99". gRPC pensa em ações: GetPedido(id: 99) — "execute essa função no servidor remoto". O resultado final é parecido, mas a filosofia de design é completamente diferente.

O que você vai aprender
🔵
REST — Arquitetura centrada em recursos
URIs, verbos HTTP, stateless. O padrão dominante da web. GitHub, Stripe, Twilio.
RESTful APIs
🟣
GraphQL
O cliente define o que quer. Resolve overfetching, underfetching e múltiplas chamadas.
Query Language
🟢
RPC & gRPC
O que é RPC, por que o Google criou o gRPC e como Protocol Buffers + HTTP/2 mudam o jogo.
Remote Procedure Call
🟡
Stateful vs Stateless
Quem guarda o estado? Por que stateless escala. JWT na prática.
Sessões & Tokens
Tabela comparativa geral
CritérioRESTGraphQLgRPC
ProtocoloHTTP/1.1HTTP/1.1 ou 2HTTP/2 obrigatório
FormatoJSONJSONProtobuf (binário)
Controle do payloadServidor decide Cliente decideContrato fixo
PerformanceBoaBoa Muito alta
Suporte no browser Nativo NativoPrecisa de proxy
Pensa em termos deRecursos / dadosCampos / grafoFunções / ações
Melhor usoAPIs públicasApps mobile, BFFsMicrosserviços internos
REST
Rotas & Verbos HTTP

A semântica está no verbo HTTP, não no nome da rota. Exemplo real: e-commerce.

Recurso: /produtos — e-commerce
GET/produtosLista todos os produtos
GET/produtos/42Retorna o produto com id 42
POST/produtosCria um novo produto
PUT/produtos/42Substitui completamente o produto 42
PATCH/produtos/42Atualiza campos específicos do produto 42
DELETE/produtos/42Remove o produto 42
Recurso aninhado: /pedidos
GET/usuarios/7/pedidosTodos os pedidos do usuário 7
GET/pedidos/99/itensItens do pedido 99
POST/pedidos/99/itensAdiciona item ao pedido 99
Códigos de status HTTP mais usados
200 OK
Leitura bem-sucedida (GET)
201 Created
Recurso criado (POST)
204 No Content
Sucesso sem corpo (DELETE)
400 Bad Request
Dados inválidos
401 Unauthorized
Sem autenticação
404 Not Found
Recurso não existe
REST
Os 6 Princípios REST

Roy Fielding definiu REST em sua dissertação de 2000. Estes são os pilares que tornam uma API verdadeiramente RESTful.

Recursos identificáveis
Cada entidade tem uma URI única e permanente. /usuarios/42 sempre é o mesmo usuário.
Representações
O recurso existe no servidor. A API retorna uma representação: JSON, XML ou HTML — o cliente escolhe via Accept.
Stateless ↓
O servidor não guarda estado de sessão. Cada requisição carrega tudo que precisa. Veja as abas abaixo.
Cache
Respostas GET podem ser cacheadas. O servidor sinaliza via headers Cache-Control e ETag.
Sistema em camadas
O cliente não sabe se fala com um proxy, CDN ou servidor real. Cada camada só conhece a seguinte.
Interface uniforme
Mesmas regras para todos os recursos. GET sempre lê, POST sempre cria. Sem surpresas.
Princípio Stateless — em profundidade

Estado é qualquer informação que precisa ser lembrada entre uma requisição e a próxima. A diferença está em quem guarda esse estado.

Stateful — problema
Quero fazer um pedido.
Ok, pode falar.
Um hambúrguer.
Anotado. Mais alguma coisa?
Sem cebola.
Ok. Bebida também?
Pode trazer a conta.
Conta de quê? Eu troquei de turno — o outro garçom não me passou nada.

O servidor precisava lembrar o contexto. Quando se perdeu, tudo quebrou.

Stateless — REST correto
1 hambúrguer sem cebola para a mesa 5.
Pedido #101 registrado.
Cancela o pedido #101 da mesa 5.
Pedido #101 cancelado.
Total da mesa 5 no pedido #101?
R$ 32,90

Cada mensagem carrega tudo. Qualquer garçom pode atender — não importa quem estava antes.

Stateful sessão no servidor
Req 1 — login
POST /login
{ "usuario": "ana", "senha": "123" }

// Servidor cria na memória:
// session["abc123"] = { userId: 7 }
Set-Cookie: sessionId=abc123
Req 2 — adiciona ao carrinho
POST /carrinho/adicionar
Cookie: sessionId=abc123
{ "produtoId": 42 }
// Busca sessão na memória ✓
Req 3 — cai em outro servidor!
GET /carrinho
Cookie: sessionId=abc123
// ❌ Servidor 2 não tem a sessão
// → carrinho vazio ou 401
Stateless token no cliente
Req 1 — login
POST /login
{ "usuario": "ana", "senha": "123" }

// Servidor NÃO guarda nada.
// Gera token assinado:
{ "token": "eyJhbGci...ana.7" }
Req 2 — adiciona ao carrinho
POST /carrinho/itens
Authorization: Bearer eyJ...
{ "produtoId": 42 }
// Valida token, extrai userId=7
Req 3 — qualquer servidor!
GET /carrinho
Authorization: Bearer eyJ...
// ✓ Qualquer servidor valida
// → 200 OK + dados do banco
Problema 1Scale horizontal
Com sessões em memória, você precisa de sticky sessions — o load balancer tem que sempre mandar o mesmo usuário para o mesmo servidor. Isso derrota o propósito do scale out. Se aquele servidor cair, o usuário perde a sessão.
Problema 2Memória no servidor
Cada usuário logado ocupa memória no servidor. Com 100k usuários simultâneos, o servidor guarda 100k sessões. No modelo stateless, o servidor é puro processamento — não acumula estado entre requisições.
Problema 3Testabilidade
Testar uma API stateful exige reproduzir a sequência exata de requisições que criou o estado. Testar uma API stateless é trivial: cada requisição é independente, basta montar o token/payload correto e a resposta é sempre determinística.
Problema 4Deploy e reinicialização
Reiniciar um servidor stateful derruba todas as sessões ativas — usuários são deslogados na hora. Um servidor stateless pode ser reiniciado, atualizado ou substituído a qualquer momento sem impacto nos usuários.
Solução intermediária: Redis

Muitos sistemas usam Redis para armazenar sessões — ainda é stateful, mas o estado sai da RAM do servidor e vai para armazenamento centralizado. Resolve o scale, mas exige infra extra. Trade-off: JWT é mais simples mas não pode ser revogado imediatamente; Redis pode invalidar na hora.

Anatomia de um JWT
# Token = 3 partes em Base64, separadas por ponto

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjcsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxOH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header:     { "alg": "HS256", "typ": "JWT" }
Payload:    { "userId": 7, "role": "admin", "exp": 1718000000 }
Assinatura: HMAC-SHA256(header + "." + payload, SECRET)

O servidor valida a assinatura com sua chave secreta. Se alguém alterar o payload, a assinatura não bate — token rejeitado automaticamente.

Fluxo de login
1
Cliente envia credenciais
Usuário + senha via POST /login
2
Servidor valida e gera JWT
Verifica no banco, assina com chave secreta
3
Token vai para o cliente
localStorage ou cookie HttpOnly
4
Toda requisição inclui o token
Authorization: Bearer eyJ...
Vantagens e limitações
✓ Vantagens
Qualquer servidor valida sem banco
Funciona entre domínios (CORS)
Expira via campo exp
Carrega role e permissions
! Limitações
Não revogável antes de expirar
Payload apenas codificado (Base64),
não criptografado
Middleware JWT — Node.js
const jwt = require('jsonwebtoken');

function autenticar(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];
  if (!token) return res.status(401).json({ erro: 'Token ausente' });
  try {
    // Valida assinatura e extrai payload — zero banco
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    req.userId = payload.userId;
    req.role   = payload.role;
    next();
  } catch {
    res.status(401).json({ erro: 'Token inválido ou expirado' });
  }
}
Usado por
GitHub APIStripeTwitter/XTwilioAWS S3Shopify
REST
REST vs não-REST

A diferença entre design RESTful e um estilo RPC-like onde tudo vira verbo na URL.

❌ Não-RESTful (RPC-like)
POST /buscarProdutos
POST /criarProduto
POST /deletarProduto
POST /atualizarProduto
GET  /getPedidosByUser?userId=7
POST /cancelarPedido
✓ RESTful
GET    /produtos
POST   /produtos
DELETE /produtos/42
PUT    /produtos/42
GET    /usuarios/7/pedidos
DELETE /pedidos/99
Por que importa?

No modelo RESTful, qualquer desenvolvedor que chegue na API já sabe o que DELETE /pedidos/99 faz — é autoexplicativo. No modelo RPC, você precisa ler a documentação de cada endpoint individualmente. REST usa o protocolo HTTP como vocabulário, tornando a API previsível e consistente.

REST
Simulador REST

Simule chamadas REST para a loja e veja a resposta. Exatamente como apresentado no chat.

Escolha uma rota
Resposta do servidor
Selecione uma rota ao lado →
// aguardando requisição...
GraphQL
O que é GraphQL

Nasceu no Facebook em 2012 para resolver um problema específico: apps mobile precisavam de dados muito precisos, mas as APIs REST devolviam dados demais (overfetching) ou de menos (underfetching).

O problema que resolve
Overfetching
REST retorna o objeto inteiro. Um app mobile que só precisa do nome e foto recebe também estoque, fornecedor, tags, peso... Desperdício de banda e processamento.
Underfetching
Para montar uma tela com dados de usuário + pedidos + recomendações, você faz 3 chamadas separadas em REST. No GraphQL, uma query única busca tudo.
Múltiplos clientes diferentes
Web, mobile, TV e relógio precisam de dados diferentes do mesmo recurso. Em REST você cria endpoints específicos ou sobra dado. No GraphQL, cada cliente faz a query que precisa.
Características principais
1
Single endpoint
Tudo via POST /graphql. Não há múltiplas rotas.
2
Schema como contrato
O servidor declara tipos. O cliente só pode pedir o que existe no schema.
3
Fortemente tipado
Erros de tipo detectados antes de chegar ao servidor.
4
Introspection
O schema é consultável via API — ferramentas como GraphiQL exploram sozinhas.
Usado por
GitHub API v4ShopifyTwitter/XFacebookAirbnbNetflix
GraphQL
Schema & Queries

O schema define o que existe. A query define o que você quer. São documentos separados — servidor e cliente têm papéis distintos.

Schema SDL — definindo tipos no servidor
type Produto {
  id:        ID!
  nome:      String!
  preco:     Float!
  categoria: String
  estoque:   Int
  tags:      [String]
}

type Query {
  produto(id: ID!): Produto
  produtos: [Produto!]!
}

type Mutation {
  criarProduto(nome: String!, preco: Float!): Produto
  deletarProduto(id: ID!): Boolean
}

O ! significa campo obrigatório (non-null). [Produto!]! = lista não-nula de produtos não-nulos.

App mobile — só o essencial
{
  produto(id: "42") {
    nome
    preco
  }
}
{ "data": { "produto": { "nome": "Tênis Air Max", "preco": 349.90 }} }
Dashboard — dados completos
{
  produto(id: "42") {
    nome
    preco
    categoria
    estoque
    tags
  }
}
{ "data": { "produto": { "nome": "Tênis Air Max", "preco": 349.90, "categoria": "calçados", "estoque": 23 }} }
Uma query, três recursos — substitui 3 chamadas REST
{
  usuario(id: "7") { nome email }
  pedidosDoUsuario(userId: "7") { id status total }
  recomendados(userId: "7") { nome preco }
}
Mutations — operações de escrita

Mutations são o equivalente ao POST/PUT/DELETE do REST — separadas explicitamente das queries de leitura.

# Criar produto
mutation {
  criarProduto(nome: "Novo Produto", preco: 99.90) {
    id
    nome
  }
}

# Atualizar com variáveis
mutation AtualizarEmail($id: ID!, $email: String!) {
  atualizarUsuario(id: $id, email: $email) {
    id
    email
  }
}
Subscriptions — dados em tempo real

Usam WebSockets para o servidor empurrar dados ao cliente quando algo muda — sem polling.

subscription {
  pedidoAtualizado(pedidoId: "99") {
    status
    updatedAt
  }
}

# Servidor empurra quando muda:
# { "data": { "pedidoAtualizado": {
#     "status": "enviado",
#     "updatedAt": "2025-06-11T14:30:00Z" }}}
GraphQL
Comparador de payload — overfetching vs GraphQL

Selecione os campos que seu cliente precisa e veja a economia real em bytes comparado ao REST.

REST — o que o servidor retorna (sempre tudo)
{
  "id": "42",
  "nome": "Tênis Air Max",
  "preco": 349.90,
  "categoria": "calçados",
  "estoque": 23,
  "peso_kg": 0.8,
  "criado_em": "2024-01-10",
  "tags": ["esporte","corrida"],
  "fornecedor_id": "F001",
  "sku": "TEN-AM-42-PRE"
}
348 bytes
sempre, independente do cliente
GraphQL — o cliente escolhe os campos
62 bytes
só o que você selecionou
82% menor que REST
Ponto de atenção

Queries muito complexas podem sobrecarregar o banco — um cliente pode pedir produtos → pedidos → usuários → pedidos de cada usuário → produtos de cada pedido, criando um grafo enorme. Exige proteção com depth limit e query cost analysis.

Introdução — gRPC
O que é RPC?

Antes de entender o gRPC, é preciso entender o conceito mais antigo no qual ele se baseia: Remote Procedure Call — Chamada de Procedimento Remoto.

A ideia central

RPC é um modelo de comunicação onde um programa chama uma função que roda em outro computador — mas o código parece uma chamada de função local. O programador não precisa pensar em sockets, serialização ou protocolo de rede. Ele simplesmente chama uma função.

Chamada local (sem rede)
# Função está no mesmo processo
resultado = calcularFrete(
  origem="SP",
  destino="RJ",
  peso=2.5
)
print(resultado)  # R$ 18.90
Chamada remota via RPC
# Função roda em outro servidor!
# O código parece idêntico:
resultado = calcularFrete(
  origem="SP",
  destino="RJ",
  peso=2.5
)
print(resultado)  # R$ 18.90

Por baixo, a chamada RPC viaja pela rede, é executada no servidor remoto e o resultado volta. Mas o desenvolvedor vê apenas uma função sendo chamada.

Como o RPC funciona por dentro
1
Cliente chama a função (stub)
O código cliente chama o que parece ser uma função local. Na verdade é um stub — um proxy gerado automaticamente que intercepta a chamada.
2
Serialização (marshalling)
O stub converte os argumentos da função para um formato que pode trafegar pela rede — bytes, JSON, XML, ou binário.
3
Transporte pela rede
Os dados viajam até o servidor remoto via TCP, HTTP, ou outro protocolo de transporte.
4
Execução no servidor (skeleton)
O servidor desserializa os dados, executa a função real, e serializa o resultado.
5
Resposta volta ao cliente
O stub desserializa o resultado e o retorna como se a função tivesse rodado localmente.
A analogia: operador telefônico

Pense no RPC como ligar para um serviço de informações. Você fala um pedido ("qual o horário do voo 1234?"), alguém do outro lado consulta o sistema e te passa a resposta. Você não sabe como eles buscaram — só sabe que pediu e recebeu.

📱
Você (cliente)
Faz o pedido sem saber os detalhes internos
📡
Rede (transporte)
Carrega o pedido e a resposta
🖥️
Servidor remoto
Executa a lógica e devolve o resultado
RPC vs REST — diferença conceitual
AspectoRPCREST
Pensa em termos deAções / funções
calcularFrete(), criarPedido()
Recursos / dados
/pedidos, /fretes
URL típica/CalcularFrete
/CriarPedido
GET /fretes
POST /pedidos
Verbo HTTPGeralmente só POSTGET, POST, PUT, DELETE…
AbstraçãoProcedimento remotoEstado de um recurso
Exemplo mental"Faça isso para mim""Me dê / guarde este recurso"
Exemplos históricos de RPC
Sun RPC (1980s) CORBA (1990s) DCOM / COM+ (Microsoft) XML-RPC (1998) SOAP / WS-* (2000s) Thrift (Facebook, 2007) Avro (Apache) gRPC (Google, 2016)

Cada geração resolveu problemas da anterior. O gRPC é a versão moderna — com HTTP/2, Protocol Buffers e suporte nativo a streaming.

Introdução — gRPC
Por que surgiu o gRPC?

O gRPC não surgiu do nada. É a evolução de décadas de tentativas de fazer chamadas remotas de forma eficiente. Entender o problema que ele resolve torna tudo mais claro.

O problema: RPC era pesado e inconsistente

Nas décadas de 1990 e 2000, o padrão era SOAP (Simple Object Access Protocol) — um formato RPC baseado em XML. Funcionava, mas era verboso ao extremo, difícil de debugar e lento.

Uma chamada SOAP simples para buscar um produto — note o XML verboso:
<!-- 📦 SOAP Request — buscar produto -->
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/">
  <soapenv:Body>
    <loja:GetProduto>
      <loja:id>42</loja:id>
    </loja:GetProduto>
  </soapenv:Body>
</soapenv:Envelope>

<!-- vs gRPC — a mesma chamada em Protobuf binário -->
# 0x0A 02 34 32  (4 bytes — id="42")
A linha do tempo até o gRPC
80s
Sun RPC & CORBA
Primeiros sistemas RPC. Funcionavam em redes locais, mas eram amarrados a linguagens e sistemas operacionais específicos. Difíceis de configurar e manter.
00s
SOAP e WS-* — o pico da complexidade
XML sobre HTTP. Interoperável entre linguagens, mas os arquivos de configuração (WSDL) eram enormes, o payload XML era pesado e o ecossistema de ferramentas era caótico. A piada era: "SOAP é tão simples que você precisa de um framework de 500MB para usá-lo."
07s
Apache Thrift (Facebook, 2007)
O Facebook precisava de RPC rápido entre centenas de serviços internos. Criou o Thrift: formato binário, geração de código automática, múltiplas linguagens. Foi a inspiração direta para o gRPC.
10s
REST domina, mas microsserviços crescem
REST com JSON virou o padrão para APIs públicas. Mas dentro das empresas, com dezenas de microsserviços se comunicando milhões de vezes por segundo, JSON sobre HTTP/1.1 começou a mostrar limitações de performance.
2016
gRPC — Google abre o código
O Google usava internamente um sistema chamado "Stubby" há mais de 10 anos. Em 2016, rebatizou como gRPC e abriu o código. Combinou o melhor de tudo: Protocol Buffers (binário eficiente), HTTP/2 (multiplexação, streaming), geração de código automática em 10+ linguagens.
O problema concreto que o gRPC resolve
⚡ Performance em microsserviços

Imagine 50 microsserviços, cada um chamando outros 5 em média, com 10.000 requisições por segundo. Com REST/JSON:
• Serialização JSON é lenta (texto → objeto → texto)
• HTTP/1.1 abre uma conexão TCP por requisição
• Headers HTTP repetidos em toda chamada

Com gRPC:
• Protobuf serializa em binário — até 10× mais rápido
• HTTP/2 reutiliza a mesma conexão para múltiplas chamadas
• Headers comprimidos com HPACK

📋 Contrato forte entre equipes
Em REST, o "contrato" da API muitas vezes é uma documentação em Notion ou Confluence que fica desatualizada. Com gRPC, o arquivo .proto é o contrato — versionado no Git, gera código automaticamente, e qualquer mudança incompatível é detectada na compilação, não em produção.
🔄 Streaming nativo
REST não tem suporte nativo a streaming bidirecional. Para casos como telemetria de IoT, feeds de dados em tempo real ou chamadas longas de processamento, REST força soluções gambiarra (long-polling, SSE). gRPC tem streaming bidirecional como cidadão de primeira classe — definido diretamente no .proto.
🌐 Múltiplas linguagens, um contrato
O time de pagamentos usa Go, o de recomendação usa Python, o de front usa Node.js. Com REST, cada equipe implementa a integração do zero e pode interpretar a documentação diferente. Com gRPC, o mesmo .proto gera stubs tipados em todas as linguagens — o contrato é o código, não o documento.
Por que não usar REST para tudo?
CenárioREST é okgRPC é melhor
API pública para terceiros Fácil de consumir Binário dificulta
100k req/s entre serviços internos JSON/HTTP1.1 pesado Binário + HTTP/2
Stream contínuo de dados (IoT) Gambiarra com SSE Streaming nativo
Times com linguagens diferentes Cada um implementa Stubs gerados do .proto
Debug e inspeção manual JSON legível Binário ilegível
App mobile / browser direto Suporte nativo Precisa de gRPC-Web
Resumo em uma frase

O gRPC surgiu porque o Google precisava de uma forma de fazer microsserviços se comunicarem com performance máxima, contrato rígido e suporte a múltiplas linguagens — e nenhuma das soluções existentes entregava os três ao mesmo tempo.

gRPC
Como funciona o gRPC

Agora que você entende RPC e por que o gRPC surgiu, veja como ele funciona por dentro: Protocol Buffers, HTTP/2 e streaming bidirecional.

Como funciona por baixo
Protocolo

HTTP/2 com multiplexação — várias chamadas simultâneas em uma só conexão TCP.

Serialização

Protocol Buffers (binário) → até 10× menor e mais rápido que JSON equivalente.

Streaming bidirecional

Cliente e servidor enviam múltiplas mensagens em ambas as direções simultaneamente.

Comparação de tamanho de payload
REST JSON348 bytes
GraphQL JSON~100 bytes
gRPC Protobuf~35 bytes
Ponto de atenção
Protobuf não é legível por humanos. Não dá pra abrir no Postman e ver o JSON — precisa de ferramentas como grpcurl. E o browser não suporta gRPC nativo: precisa de gRPC-Web proxy.
Tipos de chamada
U
Unary (padrão)
Uma requisição → uma resposta. Igual ao REST em comportamento.
S
Server streaming
Uma req → stream de respostas. Ex: listar 10 mil produtos em partes.
C
Client streaming
Stream de reqs → uma resposta. Ex: upload de arquivo em partes.
B
Bidirecional
Stream simultâneo nos dois lados. Ex: chat em tempo real, IoT, gaming.
Usado por
Google internamenteNetflixUberCloudflareKubernetes
gRPC
Protobuf & Contrato (.proto)

O arquivo .proto é o coração do gRPC. Define tipos e serviços. A partir dele, o código cliente e servidor é gerado automaticamente em qualquer linguagem.

Arquivo .proto — catálogo de produtos
syntax = "proto3";

message Produto {
  string id        = 1;
  string nome      = 2;
  float  preco     = 3;
  int32  estoque   = 4;
}

message ProdutoRequest {
  string id = 1;
}

service ProdutoService {
  rpc GetProduto(ProdutoRequest) returns (Produto);
  rpc ListarProdutos(Empty) returns (stream Produto);
}

Os números (= 1, = 2...) são IDs de campo usados na serialização binária. Nunca mude um número em produção — quebra compatibilidade com clientes antigos.

Cliente Python (gerado do .proto)
# Stubs gerados: python -m grpc_tools.protoc
import grpc
import catalogo_pb2, catalogo_pb2_grpc

channel = grpc.insecure_channel('catalogo:50051')
stub = catalogo_pb2_grpc.ProdutoServiceStub(channel)

# Chamada unary
resp = stub.GetProduto(catalogo_pb2.ProdutoRequest(id="42"))
print(resp.nome, resp.preco)

# Chamada streaming
for produto in stub.ListarProdutos(catalogo_pb2.ListaVazia()):
    print(produto.nome)
Cliente Node.js
const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const def = protoLoader.loadSync('catalogo.proto');
const proto = grpc.loadPackageDefinition(def).catalogo;

const client = new proto.ProdutoService(
  'catalogo:50051',
  grpc.credentials.createInsecure()
);

client.GetProduto({ id: '42' }, (err, produto) => {
  console.log(produto.nome, produto.preco);
});
Cliente Go
// protoc --go_out=. --go-grpc_out=. catalogo.proto
conn, _ := grpc.Dial("catalogo:50051", grpc.WithInsecure())
defer conn.Close()

client := pb.NewProdutoServiceClient(conn)
produto, _ := client.GetProduto(
  context.Background(),
  &pb.ProdutoRequest{Id: "42"},
)
fmt.Println(produto.Nome, produto.Preco)
Stateful & Stateless
A analogia do garçom

Estado é qualquer informação que precisa ser lembrada entre uma requisição e a próxima. A diferença está em quem guarda esse estado.

Stateful — problema
Quero fazer um pedido.
Ok, pode falar.
Um hambúrguer.
Anotado. Mais alguma coisa?
Sem cebola.
Ok. Bebida também?
Pode trazer a conta.
Conta de quê? Eu troquei de turno — o outro garçom não me passou nada.

O servidor precisava lembrar o contexto de todas as mensagens anteriores. Quando o contexto se perdeu, tudo quebrou.

Stateless — REST correto
1 hambúrguer sem cebola para a mesa 5.
Pedido #101 registrado.
Cancela o pedido #101 da mesa 5.
Pedido #101 cancelado.
Total da mesa 5 no pedido #101?
R$ 32,90

Cada mensagem carrega tudo que o servidor precisa. Qualquer garçom pode atender — não importa quem estava antes.

Stateful & Stateless
No HTTP — sessão vs token

A diferença prática entre uma API que guarda sessão no servidor e uma que delega o estado ao cliente via token.

Stateful sessão no servidor
Req 1 — login
POST /login
{ "usuario": "ana", "senha": "123" }

// Servidor cria na memória:
// session["abc123"] = { userId: 7 }
Set-Cookie: sessionId=abc123
Req 2 — adiciona ao carrinho
POST /carrinho/adicionar
Cookie: sessionId=abc123
{ "produtoId": 42 }
// Busca sessão na memória ✓
Req 3 — cai em outro servidor!
GET /carrinho
Cookie: sessionId=abc123
// ❌ Servidor 2 não tem a sessão
// → carrinho vazio ou 401
Stateless token no cliente
Req 1 — login
POST /login
{ "usuario": "ana", "senha": "123" }

// Servidor NÃO guarda nada.
// Gera token assinado:
{ "token": "eyJhbGci...ana.7" }
Req 2 — adiciona ao carrinho
POST /carrinho/itens
Authorization: Bearer eyJ...
{ "produtoId": 42 }
// Valida token, extrai userId=7
Req 3 — qualquer servidor!
GET /carrinho
Authorization: Bearer eyJ...
// ✓ Qualquer servidor valida
// → 200 OK + dados do banco
Stateful & Stateless
Por que stateful escala mal

Cada um desses problemas aparece em produção. Clique para expandir.

Problema 1Scale horizontal
Com sessões em memória, você precisa de sticky sessions — o load balancer tem que sempre mandar o mesmo usuário para o mesmo servidor. Isso derrota o propósito do scale out. Se aquele servidor cair, o usuário perde a sessão.
Problema 2Memória no servidor
Cada usuário logado ocupa memória no servidor. Com 100k usuários simultâneos, o servidor guarda 100k sessões. No modelo stateless, o servidor é puro processamento — não acumula estado entre requisições.
Problema 3Testabilidade
Testar uma API stateful exige reproduzir a sequência exata de requisições que criou o estado. Testar uma API stateless é trivial: cada requisição é independente, basta montar o token/payload correto e a resposta é sempre determinística.
Problema 4Deploy e reinicialização
Reiniciar um servidor stateful derruba todas as sessões ativas — usuários são deslogados na hora. Um servidor stateless pode ser reiniciado, atualizado ou substituído a qualquer momento sem impacto nos usuários.
Solução intermediária: sessão em Redis

Muitos sistemas usam Redis para armazenar sessões — ainda é tecnicamente stateful, mas melhor: o estado sai da memória local do servidor e vai para um armazenamento centralizado. Resolve o scale, mas ainda é mais complexo que JWT puro. A escolha depende de um trade-off: JWT é mais simples, mas não pode ser revogado imediatamente; sessão em Redis pode ser invalidada na hora, mas exige a infraestrutura extra.

Stateful & Stateless
JWT — autenticação stateless

JSON Web Token é o padrão para autenticação stateless. O token carrega tudo que o servidor precisa — sem consultar banco ou sessão.

Anatomia de um JWT
# Token = 3 partes separadas por ponto, cada uma em Base64

eyJhbGciOiJIUzI1NiJ9.eyJ1c2VySWQiOjcsInJvbGUiOiJhZG1pbiIsImV4cCI6MTcxOH0.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c

Header:     { "alg": "HS256", "typ": "JWT" }
Payload:    { "userId": 7, "role": "admin", "exp": 1718000000 }
Assinatura: HMAC-SHA256(header + "." + payload, SECRET)

O servidor valida a assinatura com sua chave secreta. Se alguém alterar o payload, a assinatura não bate — token rejeitado automaticamente.

Fluxo de login
1
Cliente envia credenciais
Usuário + senha via POST /login
2
Servidor valida e gera JWT
Verifica no banco, assina com chave secreta
3
Token vai para o cliente
localStorage ou cookie HttpOnly
4
Toda requisição inclui o token
Authorization: Bearer eyJ...
Vantagens e limitações
✓ Vantagens
Qualquer servidor valida sem consultar banco
Funciona entre domínios (microsserviços, CORS)
Expira automaticamente via campo exp
Carrega dados extras (role, permissions)
! Limitações
Não pode ser invalidado antes de expirar
Solução: blacklist em Redis (mas fica stateful)
Payload é codificado (Base64), não criptografado
Middleware JWT — Node.js
const jwt = require('jsonwebtoken');

function autenticar(req, res, next) {
  const token = req.headers.authorization?.split(' ')[1];

  if (!token) return res.status(401).json({ erro: 'Token ausente' });

  try {
    // Valida assinatura e extrai payload — zero banco
    const payload = jwt.verify(token, process.env.JWT_SECRET);
    req.userId = payload.userId;
    req.role   = payload.role;
    next();
  } catch {
    res.status(401).json({ erro: 'Token inválido ou expirado' });
  }
}

// Uso em qualquer rota
app.get('/perfil', autenticar, (req, res) => {
  res.json({ mensagem: `Olá, usuário ${req.userId}` });
});
REST vs GraphQL vs gRPC

Tabela completa com todos os critérios relevantes, exatamente como apresentado no comparativo do chat.

CaracterísticaGraphQLgRPC
ProtocoloHTTP/1.1 ou 2HTTP/2 obrigatório
FormatoJSON (legível)Protobuf (binário)
PerformanceBoaMuito alta (~10× menor)
Flexibilidade de query Cliente define a forma Contrato fixo no .proto
StreamingSubscriptions (WebSocket) Nativo bidirecional
Suporte no browser NativoPrecisa de proxy
TipagemSchema SDLProtobuf (mais rígido)
Melhor usoAPIs públicas, BFFs, mobileMicrosserviços internos
CritérioRESTGraphQLgRPC
ProtocoloHTTP/1.1HTTP/1.1 ou 2HTTP/2 obrigatório
Formato de dadosJSON / XMLJSONProtobuf (binário)
Controle do payloadServidor decide Cliente decideContrato fixo
Overfetching Sim NãoN/A
Múltiplas chamadas Possível Query únicaDepende
PerformanceBoaBoa Muito alta
StreamingLimitadoSubscriptions (WS) Bidirecional nativo
Suporte no browser Nativo NativoPrecisa de proxy
Depuração Muito fácilMédiaDifícil (binário)
Curva de aprendizadoBaixaMédiaAlta
Quando usar cada um

Na prática, arquiteturas modernas usam as três abordagens juntas — cada uma no papel certo.

REST
APIs públicas documentadas
Integrações com terceiros
Sistemas simples CRUD
Quando legibilidade importa
GraphQL
Apps mobile (economia de dados)
BFF (Backend for Frontend)
Múltiplos clientes diferentes
Dados em tempo real (subs)
gRPC
Microsserviços internos
Alta frequência de chamadas
IoT e dispositivos embarcados
Streaming bidirecional
Arquitetura real — e-commerce em escala

Um sistema moderno tipicamente combina as três em camadas:

1
RESTAPI Gateway público
Parceiros e integrações externas consomem REST documentado. Qualquer linguagem, qualquer ferramenta, sem configuração especial.
2
GraphQLBFF para apps mobile e web
O app React e o app mobile fazem queries GraphQL. Cada cliente busca exatamente o que precisa em uma única chamada.
3
gRPCComunicação entre microsserviços
Por trás, os serviços de catálogo, pagamento, estoque e entrega se comunicam via gRPC — ultra-rápido, tipado, sem overhead de JSON.
GraphQL · gRPC · Simulador · Comparativo

As quatro abas do explorador original do chat, reunidas em uma única tela.

Schema (contrato do servidor)
type Produto {
  id:        ID!
  nome:      String!
  preco:     Float!
  categoria: String
  estoque:   Int
}

type Query {
  produto(id: ID!): Produto
  produtos: [Produto!]!
}
Query (o cliente decide o que quer)
App mobile — só o essencial
{
  produto(id: "42") {
    nome
    preco
  }
}
Dashboard — tudo completo
{
  produto(id: "42") {
    nome
    preco
    categoria
    estoque
  }
}
Busca múltipla em uma única requisição (sem overfetching)
# Em REST precisaria de 3 chamadas. No GraphQL: uma só.
{
  usuario(id: "7") { nome email }
  pedidosDoUsuario(userId: "7") { id status total }
  recomendados(userId: "7") { nome preco }
}
Usado porGitHub API v4, Shopify, Twitter/X, Facebook, Airbnb
Ideal paraApps mobile, múltiplos clientes com necessidades diferentes, BFFs
AtençãoQueries complexas podem sobrecarregar o banco. Exige proteção com depth limit e query cost analysis.
Contrato Protobuf (.proto)
syntax = "proto3";

message Produto {
  string id      = 1;
  string nome    = 2;
  float  preco   = 3;
  int32  estoque = 4;
}

message ProdutoRequest {
  string id = 1;
}

service ProdutoService {
  rpc GetProduto(ProdutoRequest)
      returns (Produto);
  rpc ListarProdutos(Empty)
      returns (stream Produto);
}
Como funciona por baixo
Protocolo

HTTP/2 com multiplexação — várias chamadas simultâneas em uma só conexão TCP.

Serialização

Protocol Buffers (binário) → até 10× menor que JSON equivalente.

Streaming bidirecional

Cliente e servidor podem enviar múltiplas mensagens em ambas as direções simultaneamente.

Chamada em Python (gerado automaticamente pelo .proto)
# O stub é gerado automaticamente — tipado, validado
import produto_pb2_grpc, produto_pb2

channel = grpc.insecure_channel('catalogo:50051')
stub = produto_pb2_grpc.ProdutoServiceStub(channel)

resp = stub.GetProduto(produto_pb2.ProdutoRequest(id="42"))
print(resp.nome, resp.preco)
Usado porGoogle internamente, Netflix, Uber, Cloudflare, Kubernetes
Ideal paraMicrosserviços internos, comunicação de baixa latência, IoT, streaming de dados
AtençãoNão é legível por humanos (binário). Browser não suporta nativamente — precisa de proxy (gRPC-Web).

Simule o problema de overfetching do REST e como o GraphQL resolve — selecione os campos que o cliente precisa:

REST — o que o servidor retorna
{
  "id": "42",
  "nome": "Tênis Air Max",
  "preco": 349.90,
  "categoria": "calçados",
  "estoque": 23,
  "peso_kg": 0.8,
  "criado_em": "2024-01-10",
  "tags": ["esporte","corrida"],
  "fornecedor_id": "F001",
  "sku": "TEN-AM-42-PRE"
}
GraphQL — o cliente escolhe

Selecione os campos desejados:

{ produto(id: "42") { nome preco } }
Tamanho REST (sempre)
348 bytes
Tamanho GraphQL (selecionado)
62 bytes
Economia
82%
CaracterísticaGraphQLgRPC
ProtocoloHTTP/1.1 ou 2HTTP/2 obrigatório
FormatoJSON (legível)Protobuf (binário)
PerformanceBoaMuito alta (~10× menor)
Flexibilidade de query Cliente define a forma Contrato fixo no .proto
StreamingSubscriptions (WebSocket) Nativo bidirecional
Suporte no browser NativoPrecisa de proxy
TipagemSchema SDLProtobuf (mais rígido)
Melhor usoAPIs públicas, BFFs, mobileMicrosserviços internos
CritérioRESTGraphQLgRPC
ProtocoloHTTP/1.1HTTP/1.1 ou 2HTTP/2 obrigatório
Formato de dadosJSON / XMLJSONProtobuf (binário)
Controle do payloadServidor decide Cliente decideContrato fixo
Overfetching Sim NãoN/A
PerformanceBoaBoa Muito alta
StreamingLimitadoSubscriptions (WS) Bidirecional nativo
Suporte no browser Nativo NativoPrecisa de proxy
Depuração Muito fácilMédiaDifícil (binário)
Curva de aprendizadoBaixaMédiaAlta
Exercício prático
Escolha a arquitetura certa

Quatro cenários do mundo real. Para cada um, escolha a arquitetura de API e a arquitetura de sistema que você usaria. Ao confirmar, veja o gabarito com a justificativa completa.

0
pontos
0 / 4
respondidos