Alguns dias atrás fui puxado pra uma conversa curiosa: o time estava animado implementando autoscaling em pods consumidores de fila, querendo aumentar a vazão.
Tudo certo até aqui, né?
Mas aí veio a pergunta:
“Por que estamos subindo mais pods, se nem dentro de um único pod estamos aproveitando bem os recursos?”
Silêncio.
E é aí que mora o problema. Não é porque a infraestrutura é escalável que você precisa sair fazendo “Let it Go” com os pods — e deixar a conta (de CPU, memória e caos) pra outro resolver.
Hoje, bora falar de um erro comum: confundir concorrência com paralelismo.
Spoiler: não são a mesma coisa. E a diferença entre eles pode decidir se seu sistema escala bem ou só queima recurso.
Concorrência ≠ Paralelismo
Concorrência
Concorrência é sobre lidar com várias tarefas ao mesmo tempo, mas não necessariamente executá-las simultaneamente.
É como se um único core estivesse resolvendo várias coisas ao mesmo tempo, pulando de uma pra outra quando encontra espera (tipo chamadas de I/O, acesso a banco, APIs externas etc).
Você ganha desempenho não por fazer tudo ao mesmo tempo, mas por não ficar parado esperando.
Exemplo prático:
- Um worker que consome uma fila, faz uma requisição a uma API e… espera. → Nesse tempo, ele poderia estar processando outra tarefa. → Solução: aplicar concorrência, como goroutines (Go), threads leves (Java), async/await (Node, Python).
Paralelismo
Já o paralelismo é quando você tem vários núcleos (cores) processando coisas diferentes ao mesmo tempo, de verdade.
Ideal pra tarefas pesadas, como transformação de dados, processamento em lote, machine learning, etc.
Exemplo prático:
- Processar 1 milhão de registros com Spark, distribuindo o trabalho em vários nós ao mesmo tempo.
Mas cuidado: paralelismo cego com I/O intenso pode ser ineficiente.
Você cria um monte de worker… que ficam parados esperando resposta da rede.
Quando usar cada um?
Use concorrência quando…
- Seu código depende de chamadas externas (APIs, banco de dados, sistemas legados)
- Você quer melhor aproveitamento de um único recurso (ex: um pod)
Use paralelismo quando…
- Você está lidando com tarefas CPU-bound
- Precisa escalar processamento real, e não só orquestração
Apesar de eu explicar os dois separadamente, a utilização de um não inviabiliza o outro! na verdade você precisa usar os dois, mas a forma de implementação de cada um é diferente.
E os riscos?
Concorrência sem controle
- Ficar subindo muita concorrência, faz com que ela fique trocando o contexto entre elas(Context switching), e a troca de contexto de forma exagerada pode gerar overhead
- Pode explodir em race conditions, deadlocks e travar tudo (por isso você precisa ser cuidadoso e tratar isso através de mutex e lockers)
Paralelismo mal dimensionado
- Criar pods demais, sem avaliar o uso real
- Aumentar o número de threads sem controle (e o hardware é finito, lembra?)
- Escalar sem aplicar rate limit → desastre anunciado
Conclusão
A diferença entre concorrência e paralelismo pode parecer sutil, mas ignorá-la pode custar caro — em performance, em dinheiro e em complexidade desnecessária.
A verdade é que tem muita arquitetura sendo decidida no impulso. Soluções são vendidas como indispensáveis, o hype toma conta… e de repente estamos pagando caro por infraestrutura que nem traz ganho real pro negócio.
Na Comunidade Arquitetura Descomplicada, a gente debate justamente isso:
como fazer escolhas técnicas com intenção, clareza e propósito.
Se você quer sair do modo automático e começar a construir sistemas modernos, resilientes e eficientes de verdade, vem conhecer a CAD.
👉 Na CAD é onde a arquitetura deixa de ser buzzword.