AVISO: esta série é uma fantasia satírica baseada em fatos reais sobre Elixir. Nada aqui deve ser levado ao pé da letra. Ao final de cada capítulo, os fatos por trás da lenda são revelados. Tags: #satire #humor #elixir #enchiridium
Elixir Enchiridium — Tomo VI: A Batalha
Capítulos 61 a 100 (reescritos com pesquisa)
Capítulo 61 — O Cookie: O Segredo que Nunca é Enviado em Claro
A lenda diz que o cookie é um segredo. Ele nunca é enviado em claro. Ele nunca é transmitido. Ele é usado em um desafio-resposta. O cliente prova que conhece o cookie. O servidor verifica. Se o digest bater, a conexão é permitida. Se não, é negada. O cookie é a senha. O cookie é a lei.
A verdade é que o cookie é usado para autenticar a distribuição Erlang. Os cookies nunca são enviados em claro, e o procedimento de handshake espera que o cliente (chamado A) seja o primeiro a provar que pode gerar um digest suficiente. O digest é um hash MD5 de 16 bytes do Challenge (como texto) concatenado com o cookie (como texto). Os cookies são strings de texto que podem ser vistas como senhas. O valor do cookie não é transmitido na rede (um mecanismo de desafio/resposta é usado), mas nenhuma proteção está em vigor contra um ataque ativo (man-in-the-middle). Por padrão, o protocolo de distribuição transmite todos os dados da aplicação em claro, usando uma variante do External Term Format.
A lenda diz que, na primeira vez que um programador perguntou "O cookie é seguro?", o instrutor respondeu: "Ele é uma senha. Mas não é criptografia. Use TLS."
O fato por trás da lenda: O cookie autentica a distribuição Erlang via desafio-resposta. Nunca é enviado em claro. O digest é um hash MD5 do Challenge concatenado com o cookie. Mas não há proteção contra man-in-the-middle. Os dados da aplicação são transmitidos em claro por padrão.
Gancho: O cookie autentica. Mas há uma coisa que protege a conexão: o TLS.
Capítulo 62 — TLS na Distribuição: A Armadura que a BEAM Veste
A lenda diz que a BEAM andava nua pela rede. Todos podiam ver suas mensagens. Todos podiam ler seus segredos. E então alguém disse: "Vista uma armadura." E a BEAM vestiu TLS. E as mensagens ficaram criptografadas. E os segredos ficaram seguros. E os man-in-the-middle choraram.
A verdade é que, por causa das limitações da autenticação baseada em cookie e para garantir a confidencialidade e integridade dos dados trocados entre nós, o uso de TLS é recomendado. Todos os nós Erlang participantes em um sistema distribuído devem usar este módulo de distribuição. A opção {verify, verify_peer} deve estar presente nas opções do cliente, juntamente com um {cacertfile, Path} apontando para o certificado da CA raiz usado para emitir os certificados dos nós. O uso de autenticação TLS mútua, usando um certificado de cliente e {verify, verify_peer} nas opções do servidor, é recomendado.
No entanto, uma vulnerabilidade recente (CVE-2026-48860) foi descoberta no módulo inet_tls_dist do Erlang/OTP. A função inet_tls_dist:check_ip/1, que impõe uma allowlist de LAN para distribuição Erlang sobre TLS, chama inet:sockname/1 em vez de inet:peername/1 para obter o endereço IP do peer. Como inet:sockname/1 retorna o endereço do socket local, tanto o IP local quanto o suposto IP do peer resolvem para o mesmo valor, fazendo com que a comparação da máscara de sub-rede sempre tenha sucesso, independentemente do endereço remoto real. Qualquer portador de um certificado TLS assinado por uma CA pode, portanto, contornar a restrição de LAN e obter acesso total à distribuição Erlang do nó, incluindo rpc:call/4 e code:load_binary/3.
A lenda diz que, na primeira vez que um programador ativou TLS, ele perguntou: "Agora está seguro?" O instrutor respondeu: "Agora está mais seguro. Mas mantenha o OTP atualizado."
O fato por trás da lenda: Erlang Distribution over TLS criptografa conexões de distribuição. A autenticação TLS mútua é recomendada. No entanto, a CVE-2026-48860 afeta a distribuição sobre TLS no OTP 26.0 até 29.0.2, 28.5.0.2 e 27.3.4.13.
Gancho: A armadura protege. Mas há uma coisa que mapeia nomes para portas: o EPMD.
Capítulo 63 — EPMD: O Cartório dos Nós que Ninguém Vê
A lenda diz que o EPMD é um cartório. Ele mapeia nomes de nós para portas. Ele fica rodando na sombra. Ele nunca aparece. Ele nunca reclama. Ele só registra. Ele só responde. Sem ele, os nós não se encontram. Sem ele, a distribuição não funciona. E se alguém o atacar, o cluster cai.
A verdade é que EPMD (Erlang Port Mapper Daemon) é um serviço que permite descoberta de nós por nome. Ele pode ser iniciado diretamente através do executável epmd, ou implicitamente pelo primeiro nó em um host (a menos que o argumento -start_epmd false seja passado para a VM). O EPMD normalmente escuta na porta 4369. O protocolo EPMD permite que clientes não autenticados procurem um nó por nome, bem como recuperem a lista completa de nós conhecidos. A resposta inclui a porta TCP na qual o protocolo de distribuição do nó pode ser alcançado. Executar o EPMD em uma rede não confiável, portanto, expõe informações sobre os clusters Erlang distribuídos conhecidos no host.
A lenda diz que, na primeira vez que um programador perguntou "O que é EPMD?", o instrutor respondeu: "É o cartório. E o cartório fica na sombra. Proteja-o."
O fato por trás da lenda: EPMD mapeia nomes de nós para portas. Escuta na porta 4369. O protocolo permite que clientes não autenticados recuperem a lista completa de nós conhecidos. Deve ser isolado de redes não confiáveis.
Gancho: O cartório registra. Mas há uma coisa que explica os limites: o Teorema CAP.
Capítulo 64 — CAP: O Teorema que a BEAM Ignora (ou Não)
A lenda diz que, quando os aliens criaram a BEAM, eles leram o Teorema CAP e disseram: "Vamos escolher AP." E assim fizeram. A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP.
A verdade é que o Horde, por exemplo, é eventualmente consistente, o que significa que pode garantir disponibilidade e tolerância a partição. Quando a associação ao cluster do Horde é constante (ou seja, não há nós sendo adicionados ou removidos), o Horde também garante consistência. Quando um nó é adicionado ou removido do cluster, há uma pequena janela na qual isso não é verdade. O Horde escolhe o lado AP do Teorema CAP.
No entanto, existe o Paxtor, uma biblioteca Elixir para construir sistemas distribuídos CP (Consistent and Partition-tolerant) no BEAM. O Paxtor é baseado no PaxosKV, que fornece uma camada de consenso baseada no algoritmo Basic Paxos.
A lenda diz que, na primeira vez que um programador ouviu falar do CAP, ele perguntou: "Qual lado é melhor?" O instrutor respondeu: "Depende do que você não pode perder."
O fato por trás da lenda: O Horde é eventualmente consistente, garantindo disponibilidade e tolerância a partição (AP), mas também consistência quando a associação ao cluster é constante. O Paxtor é uma biblioteca CP que usa Paxos.
Gancho: O teorema explica. Mas há uma coisa que a BEAM faz melhor: tolerância a falhas.
Capítulo 65 — Horde: O Supervisor que Não Conhece Fronteiras
A lenda diz que o Horde é um supervisor. Mas não é um supervisor comum. Ele supervisiona através de nós. Ele distribui processos. Ele mantém um registro. Ele é construído sobre DeltaCrdt. Ele é eventualmente consistente. Ele nunca perde um processo. Ele nunca deixa um nó sozinho.
A verdade é que Horde é composto por Horde.Supervisor, um supervisor distribuído, e Horde.Registry, um registro distribuído. Horde é construído sobre DeltaCrdt. Como Horde é construído sobre CRDTs, ele é eventualmente consistente (em vez de imediatamente consistente), embora sincronize seu estado com seus vizinhos de forma bastante agressiva. A associação ao cluster no Horde é totalmente dinâmica; nós podem ser adicionados e removidos a qualquer momento e o Horde continuará operando conforme esperado. Horde.Supervisor também usa um anel de hash para limitar quaisquer condições de corrida a momentos em que a associação ao cluster está mudando. Horde.Registry é API-compatível com o Registry do Elixir, embora ainda não suporte a opção keys: :duplicate. Se um nó falha (ou se torna inalcançável), o Horde.Supervisor redistribuirá os processos entre os nós restantes. Você pode escolher o que fazer em caso de partição de rede especificando :distribution_strategy. Horde.UniformDistribution (o padrão) distribui processos usando um mecanismo de hash entre todos os nós alcançáveis. Em caso de partição de rede, ambos os lados da partição continuarão a operar. Horde.UniformQuorumDistribution opera da mesma forma, mas desliga se menos da metade do cluster estiver alcançável.
A lenda diz que, na primeira vez que um programador usou Horde, ele perguntou: "O que acontece se um nó cair?" O instrutor respondeu: "Os processos se mudam."
O fato por trás da lenda: Horde é um supervisor distribuído e registro construído sobre DeltaCrdt. É eventualmente consistente, garantindo disponibilidade e tolerância a partição. Usa anel de hash para limitar condições de corrida. Se um nó cai, os processos são redistribuídos. UniformQuorumDistribution desliga se menos da metade do cluster estiver alcançável.
Gancho: O supervisor distribui. Mas há uma coisa que coordena nomes globalmente: o módulo global.
Capítulo 66 — O Módulo global: O Cartório dos Nomes Distribuídos
A lenda diz que o módulo global é um cartório. Ele registra nomes. Ele notifica todos os nós. Ele monitora nós. Ele mantém a rede totalmente conectada. Ele é o cartório dos nomes distribuídos. Ele nunca perde um nome. Ele nunca deixa um nó sozinho.
A verdade é que o módulo global fornece registro de nomes globalmente distribuído. Ele consiste em serviços para: registro global de nomes, locks globais, e manutenção da rede totalmente conectada. Esses serviços são controlados através do processo global_name_server, que existe em cada nó. O global é iniciado automaticamente quando um nó é iniciado. A capacidade de registrar nomes globalmente é um conceito central na programação de sistemas Erlang distribuídos. Um nome registrado é um alias para um process identifier (pid). O global name server monitora pids globalmente registrados. Se um processo termina, o nome é globalmente desregistrado. Os nomes registrados são armazenados em tabelas de nomes globais replicadas em cada nó. Não há ponto de armazenamento central. A tradução de um nome para um pid é rápida, pois é sempre feita localmente.
A partir do OTP 25, o global irá, por padrão, prevenir partições sobrepostas devido a problemas de rede, desconectando ativamente de nós que relatam ter perdido conexões com outros nós. Isso fará com que partições totalmente conectadas se formem em vez de deixar a rede em um estado com partições sobrepostas. Uma rede de partições sobrepostas pode causar o estado interno do global se tornar inconsistente. Tal inconsistência pode permanecer mesmo depois que tais partições forem reunidas para formar uma rede totalmente conectada novamente. É fortemente recomendado não desabilitar esta correção. Note que esta correção deve ser habilitada em todos os nós da rede para funcionar corretamente.
A lenda diz que, na primeira vez que um programador usou global, ele perguntou: "Onde está o nome?" O instrutor respondeu: "No cartório. E o cartório está em todo lugar."
O fato por trás da lenda: O módulo global fornece registro de nomes globalmente distribuído. A partir do OTP 25, previne partições sobrepostas desconectando ativamente nós que perderam conexões. A correção deve ser habilitada em todos os nós.
Gancho: O cartório registra. Mas há uma coisa que testa partições: o Schism.
Capítulo 67 — Schism: O Feiticeiro que Parte a Rede
A lenda diz que o Schism é um feiticeiro. Ele parte a rede. Ele simula netsplits. Ele testa partições. Ele usa um truque com cookies. Ele nunca erra. Ele nunca deixa uma partição passar despercebida.
A verdade é que Schism é uma ferramenta de teste de partição para Elixir. Ele fornece uma API simples para testar partições entre nós BEAM. O motivo de existência do Schism é testar netsplits entre BEAMs de forma rápida e fácil, e ele usa um truque rudimentar com cookies para atingir esse objetivo. Schism é usado em conjunto com ferramentas como local_cluster e propcheck. Ele não é recomendado para uso em produção. Schism não testa conexões TCP falhas, intercalação de mensagens, condições de corrida, clock skew, corrupção, ou qualquer um dos outros problemas que você verá em um sistema distribuído.
A lenda diz que, na primeira vez que um programador usou Schism, ele perguntou: "O que é um netsplit?" O instrutor respondeu: "É quando a rede se parte ao meio. E o Schism te ajuda a testar isso."
O fato por trás da lenda: Schism é uma ferramenta de teste de partição para Elixir. Usa um truque com cookies. Não é recomendado para produção. Não testa conexões TCP falhas, intercalação de mensagens, condições de corrida, clock skew ou corrupção.
Gancho: O feiticeiro parte. Mas há uma coisa que lida com partições: o global_supervisor.
Capítulo 68 — Partisan: A Alternativa à Distribuição Totalmente Conectada
A lenda diz que o Partisan é uma alternativa. Ele não usa a distribuição totalmente conectada do Erlang. Ele usa topologias de rede alternativas. Ele é mais escalável. Ele é mais configurável. Ele é mais complexo. Ele nunca substitui a BEAM. Ele apenas a complementa.
A verdade é que Partisan é uma biblioteca que fornece uma alternativa à distribuição Erlang nativa, com foco em escalabilidade e configurabilidade. Ele contorna o uso do Distributed Erlang para gerenciamento manual de conexões via TCP, e tem vários backends plugáveis para diferentes cenários de implantação. O Erlang/OTP, especificamente o distributed erlang (disterl), usa uma rede de overlay full-mesh. Isso significa que, no pior caso, todos os nós estão conectados e se comunicam com todos os outros nós do sistema. Devido a esse heartbeating e outras questões na forma como o Erlang lida com certas estruturas de dados internas, sistemas Erlang apresentam um limite para o número de nós conectados que, dependendo da aplicação, fica entre 60 e 200 nós. Além disso, o Erlang conflaciona mensagens do plano de controle com mensagens da aplicação na mesma conexão TCP/IP e usa uma única conexão TCP/IP entre dois nós, tornando-o suscetível ao problema de Head-of-line blocking. Isso também leva a congestionamento e contenção que afetam ainda mais a latência. Este modelo pode escalar bem para implantações em datacenter, onde baixa latência pode ser assumida, mas não para implantações geo-distribuídas, onde a latência é não uniforme e pode mostrar ampla variância.
Partisan foi implementado em Erlang e mostrou que alcança até uma ordem de magnitude de aumento no número de nós que o sistema pode escalar através da seleção de overlay em runtime, até um aumento de 38,07x no throughput, e até 13,5x de melhoria.
A lenda diz que, na primeira vez que um programador ouviu falar de Partisan, ele perguntou: "Por que não usar a distribuição nativa?" O instrutor respondeu: "Porque ela não escala para 100 nós."
O fato por trás da lenda: Partisan é uma alternativa à distribuição Erlang nativa, focada em escalabilidade e configuridade. A distribuição totalmente conectada do Erlang tem um limite de 60 a 200 nós. Partisan alcança até 38,07x de aumento no throughput e 13,5x de melhoria.
Gancho: A alternativa existe. Mas há uma coisa que sempre foi o desafio: a partição de rede.
Capítulo 69 — Net Splits: A Emboscada que Ninguém Vê
A lenda diz que os net splits são emboscadas. A rede se parte. Os nós ficam presos em lados opostos. Cada lado acha que o outro morreu. Cada lado reinicia seus processos. Quando a rede volta, há dois exércitos de processos. A batalha é sangrenta. A batalha é confusa. A batalha é a pior parte de ser distribuído.
A verdade é que lidar com net splits é um dos maiores desafios de sistemas distribuídos. A natureza da distribuição Erlang torna net splits parciais um problema não solucionável com o mecanismo nativo, e a única forma de mitigar é usar ferramentas como Partisan. Em um cenário com 3 nós A, B e C, onde B está conectado a A e C, mas não há conexão direta entre A e C, um cliente no nó A pede ao supervisor local para iniciar um processo. A requisição é visível para A e B, mas não para C. A e B têm visões diferentes do cluster, então A pode decidir que B deve processar a requisição, e B pode escolher C. Como resultado, A não conseguirá iniciar o processo. E mesmo que B consiga de alguma forma tornar a requisição visível para C, ela retornaria um PID que não é utilizável em A.
Para prevenir que duas instâncias do mesmo processo permaneçam rodando após a cura de um netsplit, você precisa registrar cada processo filho com um nome único. Nomes locais só previnem a execução de múltiplas instâncias de um filho em um único nó; você pode usar o registro :global ou qualquer outro registro distribuído para prevenir a execução de múltiplas instâncias de um filho através do cluster.
A lenda diz que, na primeira vez que um programador viu um net split, ele perguntou: "O que aconteceu?" O instrutor respondeu: "A rede se partiu. E agora há dois de tudo."
O fato por trás da lenda: Net splits parciais são um problema não solucionável com a distribuição Erlang nativa. Ferramentas como Partisan ajudam a mitigar. Quando a partição é curada, pode haver múltiplas instâncias do mesmo processo. Registrar cada filho com nome único previne duplicatas.
Gancho: A emboscada é real. Mas há uma coisa que ajuda a lidar com ela: o global_supervisor.
Capítulo 70 — GlobalSupervisor: O General que Reinicia os Processos
A lenda diz que o global_supervisor é um general. Ele supervisiona processos. Mas não é um supervisor comum. Ele distribui processos pelo cluster. Em caso de partição de rede, cada partição reinicia os processos da outra parte. Quando a partição é curada, ele verifica se há duplicatas. Se houver, ele mata uma. O general nunca deixa dois exércitos iguais.
A verdade é que global_supervisor é um supervisor que distribui dinamicamente os filhos pelo cluster. Um GlobalSupervisor é como um DynamicSupervisor que coordena com outros GlobalSupervisors registrados com o mesmo nome no cluster para distribuir dinamicamente os filhos através do cluster. Quando você inicia um filho usando start_child/2, o global supervisor usa um algoritmo de hash consistente para decidir em qual nó ele deve ser iniciado. Quando um nó cai, todos os filhos rodando naquele nó serão redistribuídos nos nós restantes. Quando um novo nó é adicionado ao cluster, o global supervisor por padrão automaticamente rebalanceia a distribuição dos filhos em execução. Em caso de uma partição de rede, cada partição reinicia os filhos rodando na outra parte, assumindo que aquela parte está caída. Uma vez que a partição é curada, os filhos serão rebalanceados novamente, mas o rebalanceamento pode levar a alguns filhos sendo iniciados novamente no mesmo nó em que começaram inicialmente. Também quando o auto balanceamento está desabilitado, um netsplit curado pode ter múltiplas instâncias do mesmo filho rodando em dois ou mais nós. Para prevenir que duas instâncias do mesmo filho permaneçam rodando após um net split ser curado, você precisa registrar cada processo filho com um nome único.
A lenda diz que, na primeira vez que um programador usou global_supervisor, ele perguntou: "E se houver dois?" O instrutor respondeu: "O general mata um."
O fato por trás da lenda: global_supervisor distribui filhos pelo cluster usando hash consistente. Em caso de partição, cada partição reinicia os processos da outra. Após a cura, pode haver múltiplas instâncias. Registrar cada filho com nome único previne duplicatas.
Gancho: O general comanda. Mas há uma coisa que pula de nó em nó: o Pogo.
Capítulo 71 — Pogo: O Supervisor que Pula de Nó em Nó
A lenda diz que o Pogo é um supervisor. Mas não é um supervisor comum. Ele pula de nó em nó. Ele usa :pg por baixo dos panos. Ele mantém o estado do cluster. Ele coordena o trabalho entre supervisores locais. Ele automaticamente escolhe um nó para supervisionar um processo filho. Ele nunca deixa um processo órfão.
A verdade é que Pogo é um supervisor distribuído para aplicações Elixir em cluster. Ele usa grupos de processos nomeados distribuídos (:pg) por baixo dos panos para manter o estado do cluster e coordenar o trabalho entre supervisores locais rodando em nós diferentes. Ele automaticamente escolhe um nó para supervisionar localmente um processo filho. Um processo filho rodando no cluster pode ser iniciado ou parado usando qualquer supervisor local. Ele garante que um filho seja iniciado apenas uma vez no cluster (desde que sua especificação de filho seja única) e redistribui os filhos quando a topologia do cluster muda. Pogo tem cerca de 98 estrelas no GitHub.
A lenda diz que, na primeira vez que um programador usou Pogo, ele perguntou: "Como ele escolhe o nó?" O instrutor respondeu: "Pelo :pg. E pela magia do Pogo."
O fato por trás da lenda: Pogo é um supervisor distribuído que usa :pg para manter o estado do cluster. Escolhe automaticamente um nó para supervisionar processos. Garante que um filho seja iniciado apenas uma vez. Redistribui filhos quando a topologia do cluster muda. Cerca de 98 estrelas no GitHub.
Gancho: O supervisor pula. Mas há uma coisa que garante que um processo rode exatamente uma vez: o Chosen.
Capítulo 72 — Chosen: O Supervisor que Roda Exatamente Uma Vez
A lenda diz que o Chosen é um supervisor. Mas não é um supervisor comum. Ele garante que um processo rode exatamente uma vez em todo o cluster. Ele não precisa de clustering BEAM. Ele usa advisory locks do PostgreSQL. Ele é o supervisor singleton. Ele nunca deixa dois processos rodarem ao mesmo tempo.
A verdade é que Chosen é um supervisor singleton distribuído baseado em advisory locks do PostgreSQL. Ele garante que um processo ou supervisor rode exatamente uma vez em todo o cluster. Ele não requer clustering BEAM. Chosen usa advisory locks do PostgreSQL para garantir unicidade global. Na inicialização, Chosen tenta adquirir um lock através do LockManager compartilhado. O vencedor inicia e supervisiona o processo filho. Os perdedores esperam sua vez, fazendo polling em intervalos configuráveis. Se o detentor do lock morre ou perde a conexão, o lock é liberado automaticamente. A próxima instância adquire imediatamente o lock e inicia o filho. Garantia chave: apenas uma instância roda por vez, em todo o cluster.
A lenda diz que, na primeira vez que um programador usou Chosen, ele perguntou: "Como ele garante que só um rode?" O instrutor respondeu: "Pelo advisory lock. E pela magia do PostgreSQL."
O fato por trás da lenda: Chosen é um supervisor singleton distribuído baseado em advisory locks do PostgreSQL. Garante que um processo rode exatamente uma vez. Não requer clustering BEAM.
Gancho: O supervisor escolhe. Mas há uma coisa que combina supervisor e registro: o Sworm.
Capítulo 73 — Sworm: O Híbrido de Supervisor e Registro
A lenda diz que o Sworm é um híbrido. Ele combina o DynamicSupervisor e o Registry do Horde. Ele reproduz a biblioteca Swarm. Ele mantém um diretório CRDT global do cluster. Ele rastreia em qual nó cada tipo de Sworm roda. Ele nunca perde um registro. Ele nunca deixa um nó sozinho.
A verdade é que Sworm é uma combinação de um registro de processos global e distribuído e um supervisor, reunidos em uma API amigável. Sworm combina os módulos Horde.DynamicSupervisor e Horde.Registry para reproduzir a biblioteca Swarm. Sworm mantém um diretório CRDT global do cluster de Sworms registrados, rastreando em qual nó cada tipo de Sworm roda. Isso garante que os processos só são iniciados através do Sworm em nós onde o próprio Sworm também está rodando, em vez de assumir que o cluster é homogêneo e que os processos podem rodar em cada nó, como o Swarm faz. Para um controle ainda mais refinado sobre a colocação de processos, você pode passar uma opção personalizada :distribution_strategy em tempo de compilação. A estratégia de distribuição padrão é Horde.UniformDistribution.
A lenda diz que, na primeira vez que um programador usou Sworm, ele perguntou: "O que é isso?" O instrutor respondeu: "É o Swarm, mas com Horde por baixo."
O fato por trás da lenda: Sworm combina Horde.DynamicSupervisor e Horde.Registry. Mantém um diretório CRDT global. Rastreia em qual nó cada tipo de Sworm roda. A estratégia padrão é Horde.UniformDistribution.
Gancho: O híbrido combina. Mas há uma coisa que registra presenças: o Phoenix.Presence.
Capítulo 74 — Phoenix.Presence: O Vigia que Vê Tudo
A lenda diz que o Phoenix.Presence é um vigia. Ele vê quem está online. Ele vê quem entrou. Ele vê quem saiu. Ele replica essa informação para todos os nós. Se um nó cai, os outros sentem falta. Se um nó volta, os outros dão boas-vindas. O vigia nunca dorme. O vigia nunca esquece.
A verdade é que Phoenix.Presence fornece rastreamento de presença para processos e canais. É um behaviour que fornece recursos como buscar presenças para um tópico e lidar com diffs de eventos de join e leave em tempo real. Usar este módulo define um supervisor e permite que o módulo chamador implemente o behaviour Phoenix.Tracker, que inicia um processo tracker para lidar com informações de presença. Os tracker shards usam um protocolo de heartbeat e CRDT para replicar informações de presença através de um cluster de forma eventualmente consistente e livre de conflitos. Cada nó executa um pool de trackers e mudanças locais ao nó são replicadas através do cluster e tratadas localmente como um diff de mudanças.
A lenda diz que, na primeira vez que um programador usou Presence, ele perguntou: "Como isso funciona?" O instrutor respondeu: "Tracker shards. Heartbeat. CRDT."
O fato por trás da lenda: Phoenix.Presence fornece rastreamento de presença para processos e canais. Usa tracker shards com heartbeat e CRDT para replicar informações de presença de forma eventualmente consistente e livre de conflitos.
Gancho: O vigia vê. Mas há uma coisa que distribui mensagens: o Phoenix.PubSub.
Capítulo 75 — Phoenix.PubSub: O Megafone que Todos Ouvem
A lenda diz que o Phoenix.PubSub é um megafone. Você publica uma mensagem em um tópico. Todos os processos inscritos naquele tópico recebem a mensagem. Ninguém fica de fora. Ninguém ouve o que não devia. O megafone é justo.
A verdade é que Phoenix.PubSub é um serviço de Publisher/Subscriber em tempo real. O adapter padrão é o Phoenix.PubSub.PG2, que usa grupos de processos do Erlang para implementar o modelo PubSub onde um publisher pode enviar mensagens para muitos subscribers. O PG2 adapter usa o módulo :pg2 do Erlang (ou :pg em versões mais recentes). Em um cluster, o PubSub distribui mensagens entre os nós usando a distribuição Erlang. O Supabase Realtime, por exemplo, é um cluster Elixir globalmente distribuído que usa Phoenix.PubSub com o adapter PG2 padrão para implementar seus canais.
A lenda diz que, na primeira vez que um programador usou PubSub, ele perguntou: "Como o PubSub funciona?" O instrutor respondeu: "Você publica, eles ouvem."
O fato por trás da lenda: Phoenix.PubSub é um serviço de Publisher/Subscriber em tempo real. O adapter padrão é o PG2, que usa grupos de processos do Erlang. Em cluster, distribui mensagens entre nós usando a distribuição Erlang.
Gancho: O megafone transmite. Mas há uma coisa que registra nomes: o módulo global.
Capítulo 76 — :pg: O Grupo de Processos que Atravessa Nós
A lenda diz que o :pg é um grupo de processos. Mas não é um grupo comum. É um grupo que atravessa nós. Você entra no grupo. Outros processos entram no grupo. Todos se conhecem. Todos se falam. Se um morre, o grupo sente falta. Se um nasce, o grupo dá boas-vindas. O grupo nunca se desfaz. O grupo nunca se perde.
A verdade é que o módulo pg implementa grupos de processos distribuídos e nomeados. Uma mensagem pode ser enviada para um, alguns ou todos os membros do grupo. Um grupo de processos pode ser acessado por um nome comum. Por exemplo, se existe um grupo chamado foobar, pode haver um conjunto de processos (que podem estar localizados em nós diferentes) que são todos membros do grupo foobar. Não há funções especiais para enviar uma mensagem ao grupo. Em vez disso, funções cliente devem ser escritas com get_members/1 e get_local_members/1 para determinar quais processos são membros do grupo. Se um membro termina, ele é automaticamente removido do grupo. Process Groups implementam strong eventual consistency. A visão de associação do grupo pode divergir temporariamente. Por exemplo, quando processos em node1 e node2 entram concorrentemente, node3 e node4 podem receber atualizações em ordem diferente. Grupos são automaticamente criados quando qualquer processo entra, e removidos quando todos os processos saem.
A lenda diz que, na primeira vez que um programador usou :pg, ele perguntou: "Onde está o grupo?" O instrutor respondeu: "Em todo lugar. E em lugar nenhum. É distribuído."
O fato por trás da lenda: O módulo pg implementa grupos de processos distribuídos e nomeados. Uma mensagem pode ser enviada para um, alguns ou todos os membros do grupo. Process Groups implementam strong eventual consistency. Grupos são automaticamente criados quando qualquer processo entra, e removidos quando todos saem.
Gancho: O grupo atravessa nós. Mas há uma coisa que substitui o pg2: o :pg moderno.
Capítulo 77 — :pg2: O Módulo que Morreu para Dar Lugar ao :pg
A lenda diz que o :pg2 foi um grande general. Ele comandou grupos de processos. Ele os registrou. Ele os distribuiu. Mas ele tinha um defeito: ele não escalava. Ele ficava lento quando o exército crescia. E então, no OTP 23, os deuses da Ericsson decretaram: "O :pg2 está depreciado. Use o :pg." E o general caiu. E o :pg subiu. E o exército continuou marchando.
A verdade é que o módulo pg2 foi depreciado a partir do OTP 23 e removido no OTP 24. A recomendação oficial é substituir o uso de pg2 por pg. O pg tem uma API similar, mas com uma implementação que é muito mais escalável. O pg2 era usado para grupos de processos distribuídos, mas sua implementação não escalava bem. O Phoenix usava pg2 para agrupar canais, mas migrou para pg. A remoção do pg2 foi um marco na evolução da distribuição Erlang.
A lenda diz que, na primeira vez que um programador tentou usar pg2 no OTP 24, ele perguntou: "Onde está o pg2?" O instrutor respondeu: "Morreu. Use o pg."
O fato por trás da lenda: O módulo pg2 foi depreciado a partir do OTP 23 e removido no OTP 24. A recomendação é substituir por pg, que tem API similar mas implementação mais escalável.
Gancho: O general morreu. Mas há uma coisa que protege a distribuição: o TLS.
Capítulo 78 — TLS na Distribuição: A Armadura que a BEAM Veste
A lenda diz que a BEAM andava nua pela rede. Todos podiam ver suas mensagens. Todos podiam ler seus segredos. E então alguém disse: "Vista uma armadura." E a BEAM vestiu TLS. E as mensagens ficaram criptografadas. E os segredos ficaram seguros. E os man-in-the-middle choraram.
A verdade é que, por causa das limitações da autenticação baseada em cookie e para garantir a confidencialidade e integridade dos dados trocados entre nós, o uso de TLS é recomendado. Todos os nós Erlang participantes em um sistema distribuído devem usar este módulo de distribuição. A opção {verify, verify_peer} deve estar presente nas opções do cliente, juntamente com um {cacertfile, Path} apontando para o certificado da CA raiz usado para emitir os certificados dos nós. O uso de autenticação TLS mútua, usando um certificado de cliente e {verify, verify_peer} nas opções do servidor, é recomendado.
No entanto, uma vulnerabilidade recente (CVE-2026-48860) foi descoberta no módulo inet_tls_dist do Erlang/OTP. A função inet_tls_dist:check_ip/1, que impõe uma allowlist de LAN para distribuição Erlang sobre TLS, chama inet:sockname/1 em vez de inet:peername/1 para obter o endereço IP do peer. Como inet:sockname/1 retorna o endereço do socket local, tanto o IP local quanto o suposto IP do peer resolvem para o mesmo valor, fazendo com que a comparação da máscara de sub-rede sempre tenha sucesso, independentemente do endereço remoto real. Qualquer portador de um certificado TLS assinado por uma CA pode, portanto, contornar a restrição de LAN e obter acesso total à distribuição Erlang do nó, incluindo rpc:call/4 e code:load_binary/3.
A lenda diz que, na primeira vez que um programador ativou TLS, ele perguntou: "Agora está seguro?" O instrutor respondeu: "Agora está mais seguro. Mas mantenha o OTP atualizado."
O fato por trás da lenda: Erlang Distribution over TLS criptografa conexões de distribuição. A autenticação TLS mútua é recomendada. No entanto, a CVE-2026-48860 afeta a distribuição sobre TLS no OTP 26.0 até 29.0.2, 28.5.0.2 e 27.3.4.13.
Gancho: A armadura protege. Mas há uma coisa que mapeia nomes para portas: o EPMD.
Capítulo 79 — EPMD: O Cartório dos Nós que Ninguém Vê
A lenda diz que o EPMD é um cartório. Ele mapeia nomes de nós para portas. Ele fica rodando na sombra. Ele nunca aparece. Ele nunca reclama. Ele só registra. Ele só responde. Sem ele, os nós não se encontram. Sem ele, a distribuição não funciona. E se alguém o atacar, o cluster cai.
A verdade é que EPMD (Erlang Port Mapper Daemon) é um serviço que permite descoberta de nós por nome. Ele pode ser iniciado diretamente através do executável epmd, ou implicitamente pelo primeiro nó em um host (a menos que o argumento -start_epmd false seja passado para a VM). O EPMD normalmente escuta na porta 4369. O protocolo EPMD permite que clientes não autenticados procurem um nó por nome, bem como recuperem a lista completa de nós conhecidos. A resposta inclui a porta TCP na qual o protocolo de distribuição do nó pode ser alcançado. Executar o EPMD em uma rede não confiável, portanto, expõe informações sobre os clusters Erlang distribuídos conhecidos no host.
A lenda diz que, na primeira vez que um programador perguntou "O que é EPMD?", o instrutor respondeu: "É o cartório. E o cartório fica na sombra. Proteja-o."
O fato por trás da lenda: EPMD mapeia nomes de nós para portas. Escuta na porta 4369. O protocolo permite que clientes não autenticados recuperem a lista completa de nós conhecidos. Deve ser isolado de redes não confiáveis.
Gancho: O cartório registra. Mas há uma coisa que explica os limites: o Teorema CAP.
Capítulo 80 — CAP: O Teorema que a BEAM Ignora (ou Não)
A lenda diz que, quando os aliens criaram a BEAM, eles leram o Teorema CAP e disseram: "Vamos escolher AP." E assim fizeram. A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP.
A verdade é que o Horde, por exemplo, é eventualmente consistente, o que significa que pode garantir disponibilidade e tolerância a partição. Quando a associação ao cluster do Horde é constante (ou seja, não há nós sendo adicionados ou removidos), o Horde também garante consistência. Quando um nó é adicionado ou removido do cluster, há uma pequena janela na qual isso não é verdade. O Horde escolhe o lado AP do Teorema CAP.
No entanto, existe o Paxtor, uma biblioteca Elixir para construir sistemas distribuídos CP (Consistent and Partition-tolerant) no BEAM. O Paxtor é baseado no PaxosKV, que fornece uma camada de consenso baseada no algoritmo Basic Paxos.
A lenda diz que, na primeira vez que um programador ouviu falar do CAP, ele perguntou: "Qual lado é melhor?" O instrutor respondeu: "Depende do que você não pode perder."
O fato por trás da lenda: O Horde é eventualmente consistente, garantindo disponibilidade e tolerância a partição (AP), mas também consistência quando a associação ao cluster é constante. O Paxtor é uma biblioteca CP que usa Paxos.
Gancho: O teorema explica. Mas há uma coisa que a BEAM faz melhor: tolerância a falhas.
Capítulo 81 — Horde: O Supervisor que Não Conhece Fronteiras
A lenda diz que o Horde é um supervisor. Mas não é um supervisor comum. Ele supervisiona através de nós. Ele distribui processos. Ele mantém um registro. Ele é construído sobre DeltaCrdt. Ele é eventualmente consistente. Ele nunca perde um processo. Ele nunca deixa um nó sozinho.
A verdade é que Horde é composto por Horde.Supervisor, um supervisor distribuído, e Horde.Registry, um registro distribuído. Horde é construído sobre DeltaCrdt. Como Horde é construído sobre CRDTs, ele é eventualmente consistente (em vez de imediatamente consistente), embora sincronize seu estado com seus vizinhos de forma bastante agressiva. A associação ao cluster no Horde é totalmente dinâmica; nós podem ser adicionados e removidos a qualquer momento e o Horde continuará operando conforme esperado. Horde.Supervisor também usa um anel de hash para limitar quaisquer condições de corrida a momentos em que a associação ao cluster está mudando. Horde.Registry é API-compatível com o Registry do Elixir, embora ainda não suporte a opção keys: :duplicate. Se um nó falha (ou se torna inalcançável), o Horde.Supervisor redistribuirá os processos entre os nós restantes. Você pode escolher o que fazer em caso de partição de rede especificando :distribution_strategy. Horde.UniformDistribution (o padrão) distribui processos usando um mecanismo de hash entre todos os nós alcançáveis. Em caso de partição de rede, ambos os lados da partição continuarão a operar. Horde.UniformQuorumDistribution opera da mesma forma, mas desliga se menos da metade do cluster estiver alcançável.
A lenda diz que, na primeira vez que um programador usou Horde, ele perguntou: "O que acontece se um nó cair?" O instrutor respondeu: "Os processos se mudam."
O fato por trás da lenda: Horde é um supervisor distribuído e registro construído sobre DeltaCrdt. É eventualmente consistente, garantindo disponibilidade e tolerância a partição. Usa anel de hash para limitar condições de corrida. Se um nó cai, os processos são redistribuídos. UniformQuorumDistribution desliga se menos da metade do cluster estiver alcançável.
Gancho: O supervisor distribui. Mas há uma coisa que coordena nomes globalmente: o módulo global.
Capítulo 82 — O Módulo global: O Cartório dos Nomes Distribuídos
A lenda diz que o módulo global é um cartório. Ele registra nomes. Ele notifica todos os nós. Ele monitora nós. Ele mantém a rede totalmente conectada. Ele é o cartório dos nomes distribuídos. Ele nunca perde um nome. Ele nunca deixa um nó sozinho.
A verdade é que o módulo global fornece registro de nomes globalmente distribuído. Ele consiste em serviços para: registro global de nomes, locks globais, e manutenção da rede totalmente conectada. Esses serviços são controlados através do processo global_name_server, que existe em cada nó. O global é iniciado automaticamente quando um nó é iniciado. A capacidade de registrar nomes globalmente é um conceito central na programação de sistemas Erlang distribuídos. Um nome registrado é um alias para um process identifier (pid). O global name server monitora pids globalmente registrados. Se um processo termina, o nome é globalmente desregistrado. Os nomes registrados são armazenados em tabelas de nomes globais replicadas em cada nó. Não há ponto de armazenamento central. A tradução de um nome para um pid é rápida, pois é sempre feita localmente.
A partir do OTP 25, o global irá, por padrão, prevenir partições sobrepostas devido a problemas de rede, desconectando ativamente de nós que relatam ter perdido conexões com outros nós. Isso fará com que partições totalmente conectadas se formem em vez de deixar a rede em um estado com partições sobrepostas. Uma rede de partições sobrepostas pode causar o estado interno do global se tornar inconsistente. Tal inconsistência pode permanecer mesmo depois que tais partições forem reunidas para formar uma rede totalmente conectada novamente. É fortemente recomendado não desabilitar esta correção. Note que esta correção deve ser habilitada em todos os nós da rede para funcionar corretamente.
A lenda diz que, na primeira vez que um programador usou global, ele perguntou: "Onde está o nome?" O instrutor respondeu: "No cartório. E o cartório está em todo lugar."
O fato por trás da lenda: O módulo global fornece registro de nomes globalmente distribuído. A partir do OTP 25, previne partições sobrepostas desconectando ativamente nós que perderam conexões. A correção deve ser habilitada em todos os nós.
Gancho: O cartório registra. Mas há uma coisa que testa partições: o Schism.
Capítulo 83 — Schism: O Feiticeiro que Parte a Rede
A lenda diz que o Schism é um feiticeiro. Ele parte a rede. Ele simula netsplits. Ele testa partições. Ele usa um truque com cookies. Ele nunca erra. Ele nunca deixa uma partição passar despercebida.
A verdade é que Schism é uma ferramenta de teste de partição para Elixir. Ele fornece uma API simples para testar partições entre nós BEAM. O motivo de existência do Schism é testar netsplits entre BEAMs de forma rápida e fácil, e ele usa um truque rudimentar com cookies para atingir esse objetivo. Schism é usado em conjunto com ferramentas como local_cluster e propcheck. Ele não é recomendado para uso em produção. Schism não testa conexões TCP falhas, intercalação de mensagens, condições de corrida, clock skew, corrupção, ou qualquer um dos outros problemas que você verá em um sistema distribuído.
A lenda diz que, na primeira vez que um programador usou Schism, ele perguntou: "O que é um netsplit?" O instrutor respondeu: "É quando a rede se parte ao meio. E o Schism te ajuda a testar isso."
O fato por trás da lenda: Schism é uma ferramenta de teste de partição para Elixir. Usa um truque com cookies. Não é recomendado para produção. Não testa conexões TCP falhas, intercalação de mensagens, condições de corrida, clock skew ou corrupção.
Gancho: O feiticeiro parte. Mas há uma coisa que lida com partições: o global_supervisor.
Capítulo 84 — Partisan: A Alternativa à Distribuição Totalmente Conectada
A lenda diz que o Partisan é uma alternativa. Ele não usa a distribuição totalmente conectada do Erlang. Ele usa topologias de rede alternativas. Ele é mais escalável. Ele é mais configurável. Ele é mais complexo. Ele nunca substitui a BEAM. Ele apenas a complementa.
A verdade é que Partisan é uma biblioteca que fornece uma alternativa à distribuição Erlang nativa, com foco em escalabilidade e configuridade. Ele contorna o uso do Distributed Erlang para gerenciamento manual de conexões via TCP, e tem vários backends plugáveis para diferentes cenários de implantação. O Erlang/OTP, especificamente o distributed erlang (disterl), usa uma rede de overlay full-mesh. Isso significa que, no pior caso, todos os nós estão conectados e se comunicam com todos os outros nós do sistema. Devido a esse heartbeating e outras questões na forma como o Erlang lida com certas estruturas de dados internas, sistemas Erlang apresentam um limite para o número de nós conectados que, dependendo da aplicação, fica entre 60 e 200 nós. Além disso, o Erlang conflaciona mensagens do plano de controle com mensagens da aplicação na mesma conexão TCP/IP e usa uma única conexão TCP/IP entre dois nós, tornando-o suscetível ao problema de Head-of-line blocking. Isso também leva a congestionamento e contenção que afetam ainda mais a latência. Este modelo pode escalar bem para implantações em datacenter, onde baixa latência pode ser assumida, mas não para implantações geo-distribuídas, onde a latência é não uniforme e pode mostrar ampla variância.
Partisan foi implementado em Erlang e mostrou que alcança até uma ordem de magnitude de aumento no número de nós que o sistema pode escalar através da seleção de overlay em runtime, até um aumento de 38,07x no throughput, e até 13,5x de melhoria.
A lenda diz que, na primeira vez que um programador ouviu falar de Partisan, ele perguntou: "Por que não usar a distribuição nativa?" O instrutor respondeu: "Porque ela não escala para 100 nós."
O fato por trás da lenda: Partisan é uma alternativa à distribuição Erlang nativa, focada em escalabilidade e configuridade. A distribuição totalmente conectada do Erlang tem um limite de 60 a 200 nós. Partisan alcança até 38,07x de aumento no throughput e 13,5x de melhoria.
Gancho: A alternativa existe. Mas há uma coisa que sempre foi o desafio: a partição de rede.
Capítulo 85 — Net Splits: A Emboscada que Ninguém Vê
A lenda diz que os net splits são emboscadas. A rede se parte. Os nós ficam presos em lados opostos. Cada lado acha que o outro morreu. Cada lado reinicia seus processos. Quando a rede volta, há dois exércitos de processos. A batalha é sangrenta. A batalha é confusa. A batalha é a pior parte de ser distribuído.
A verdade é que lidar com net splits é um dos maiores desafios de sistemas distribuídos. A natureza da distribuição Erlang torna net splits parciais um problema não solucionável com o mecanismo nativo, e a única forma de mitigar é usar ferramentas como Partisan. Em um cenário com 3 nós A, B e C, onde B está conectado a A e C, mas não há conexão direta entre A e C, um cliente no nó A pede ao supervisor local para iniciar um processo. A requisição é visível para A e B, mas não para C. A e B têm visões diferentes do cluster, então A pode decidir que B deve processar a requisição, e B pode escolher C. Como resultado, A não conseguirá iniciar o processo. E mesmo que B consiga de alguma forma tornar a requisição visível para C, ela retornaria um PID que não é utilizável em A.
Para prevenir que duas instâncias do mesmo processo permaneçam rodando após a cura de um netsplit, você precisa registrar cada processo filho com um nome único. Nomes locais só previnem a execução de múltiplas instâncias de um filho em um único nó; você pode usar o registro :global ou qualquer outro registro distribuído para prevenir a execução de múltiplas instâncias de um filho através do cluster.
A lenda diz que, na primeira vez que um programador viu um net split, ele perguntou: "O que aconteceu?" O instrutor respondeu: "A rede se partiu. E agora há dois de tudo."
O fato por trás da lenda: Net splits parciais são um problema não solucionável com a distribuição Erlang nativa. Ferramentas como Partisan ajudam a mitigar. Quando a partição é curada, pode haver múltiplas instâncias do mesmo processo. Registrar cada filho com nome único previne duplicatas.
Gancho: A emboscada é real. Mas há uma coisa que ajuda a lidar com ela: o global_supervisor.
Capítulo 86 — GlobalSupervisor: O General que Reinicia os Processos
A lenda diz que o global_supervisor é um general. Ele supervisiona processos. Mas não é um supervisor comum. Ele distribui processos pelo cluster. Em caso de partição de rede, cada partição reinicia os processos da outra parte. Quando a partição é curada, ele verifica se há duplicatas. Se houver, ele mata uma. O general nunca deixa dois exércitos iguais.
A verdade é que global_supervisor é um supervisor que distribui dinamicamente os filhos pelo cluster. Um GlobalSupervisor é como um DynamicSupervisor que coordena com outros GlobalSupervisors registrados com o mesmo nome no cluster para distribuir dinamicamente os filhos através do cluster. Quando você inicia um filho usando start_child/2, o global supervisor usa um algoritmo de hash consistente para decidir em qual nó ele deve ser iniciado. Quando um nó cai, todos os filhos rodando naquele nó serão redistribuídos nos nós restantes. Quando um novo nó é adicionado ao cluster, o global supervisor por padrão automaticamente rebalanceia a distribuição dos filhos em execução. Em caso de uma partição de rede, cada partição reinicia os filhos rodando na outra parte, assumindo que aquela parte está caída. Uma vez que a partição é curada, os filhos serão rebalanceados novamente, mas o rebalanceamento pode levar a alguns filhos sendo iniciados novamente no mesmo nó em que começaram inicialmente. Também quando o auto balanceamento está desabilitado, um netsplit curado pode ter múltiplas instâncias do mesmo filho rodando em dois ou mais nós. Para prevenir que duas instâncias do mesmo filho permaneçam rodando após um net split ser curado, você precisa registrar cada processo filho com um nome único.
A lenda diz que, na primeira vez que um programador usou global_supervisor, ele perguntou: "E se houver dois?" O instrutor respondeu: "O general mata um."
O fato por trás da lenda: global_supervisor distribui filhos pelo cluster usando hash consistente. Em caso de partição, cada partição reinicia os processos da outra. Após a cura, pode haver múltiplas instâncias. Registrar cada filho com nome único previne duplicatas.
Gancho: O general comanda. Mas há uma coisa que pula de nó em nó: o Pogo.
Capítulo 87 — Pogo: O Supervisor que Pula de Nó em Nó
A lenda diz que o Pogo é um supervisor. Mas não é um supervisor comum. Ele pula de nó em nó. Ele usa :pg por baixo dos panos. Ele mantém o estado do cluster. Ele coordena o trabalho entre supervisores locais. Ele automaticamente escolhe um nó para supervisionar um processo filho. Ele nunca deixa um processo órfão.
A verdade é que Pogo é um supervisor distribuído para aplicações Elixir em cluster. Ele usa grupos de processos nomeados distribuídos (:pg) por baixo dos panos para manter o estado do cluster e coordenar o trabalho entre supervisores locais rodando em nós diferentes. Ele automaticamente escolhe um nó para supervisionar localmente um processo filho. Um processo filho rodando no cluster pode ser iniciado ou parado usando qualquer supervisor local. Ele garante que um filho seja iniciado apenas uma vez no cluster (desde que sua especificação de filho seja única) e redistribui os filhos quando a topologia do cluster muda. Pogo tem cerca de 98 estrelas no GitHub.
A lenda diz que, na primeira vez que um programador usou Pogo, ele perguntou: "Como ele escolhe o nó?" O instrutor respondeu: "Pelo :pg. E pela magia do Pogo."
O fato por trás da lenda: Pogo é um supervisor distribuído que usa :pg para manter o estado do cluster. Escolhe automaticamente um nó para supervisionar processos. Garante que um filho seja iniciado apenas uma vez. Redistribui filhos quando a topologia do cluster muda. Cerca de 98 estrelas no GitHub.
Gancho: O supervisor pula. Mas há uma coisa que garante que um processo rode exatamente uma vez: o Chosen.
Capítulo 88 — Chosen: O Supervisor que Roda Exatamente Uma Vez
A lenda diz que o Chosen é um supervisor. Mas não é um supervisor comum. Ele garante que um processo rode exatamente uma vez em todo o cluster. Ele não precisa de clustering BEAM. Ele usa advisory locks do PostgreSQL. Ele é o supervisor singleton. Ele nunca deixa dois processos rodarem ao mesmo tempo.
A verdade é que Chosen é um supervisor singleton distribuído baseado em advisory locks do PostgreSQL. Ele garante que um processo ou supervisor rode exatamente uma vez em todo o cluster. Ele não requer clustering BEAM. Chosen usa advisory locks do PostgreSQL para garantir unicidade global. Na inicialização, Chosen tenta adquirir um lock através do LockManager compartilhado. O vencedor inicia e supervisiona o processo filho. Os perdedores esperam sua vez, fazendo polling em intervalos configuráveis. Se o detentor do lock morre ou perde a conexão, o lock é liberado automaticamente. A próxima instância adquire imediatamente o lock e inicia o filho. Garantia chave: apenas uma instância roda por vez, em todo o cluster.
A lenda diz que, na primeira vez que um programador usou Chosen, ele perguntou: "Como ele garante que só um rode?" O instrutor respondeu: "Pelo advisory lock. E pela magia do PostgreSQL."
O fato por trás da lenda: Chosen é um supervisor singleton distribuído baseado em advisory locks do PostgreSQL. Garante que um processo rode exatamente uma vez. Não requer clustering BEAM.
Gancho: O supervisor escolhe. Mas há uma coisa que combina supervisor e registro: o Sworm.
Capítulo 89 — Sworm: O Híbrido de Supervisor e Registro
A lenda diz que o Sworm é um híbrido. Ele combina o DynamicSupervisor e o Registry do Horde. Ele reproduz a biblioteca Swarm. Ele mantém um diretório CRDT global do cluster. Ele rastreia em qual nó cada tipo de Sworm roda. Ele nunca perde um registro. Ele nunca deixa um nó sozinho.
A verdade é que Sworm é uma combinação de um registro de processos global e distribuído e um supervisor, reunidos em uma API amigável. Sworm combina os módulos Horde.DynamicSupervisor e Horde.Registry para reproduzir a biblioteca Swarm. Sworm mantém um diretório CRDT global do cluster de Sworms registrados, rastreando em qual nó cada tipo de Sworm roda. Isso garante que os processos só são iniciados através do Sworm em nós onde o próprio Sworm também está rodando, em vez de assumir que o cluster é homogêneo e que os processos podem rodar em cada nó, como o Swarm faz. Para um controle ainda mais refinado sobre a colocação de processos, você pode passar uma opção personalizada :distribution_strategy em tempo de compilação. A estratégia de distribuição padrão é Horde.UniformDistribution.
A lenda diz que, na primeira vez que um programador usou Sworm, ele perguntou: "O que é isso?" O instrutor respondeu: "É o Swarm, mas com Horde por baixo."
O fato por trás da lenda: Sworm combina Horde.DynamicSupervisor e Horde.Registry. Mantém um diretório CRDT global. Rastreia em qual nó cada tipo de Sworm roda. A estratégia padrão é Horde.UniformDistribution.
Gancho: O híbrido combina. Mas há uma coisa que registra presenças: o Phoenix.Presence.
Capítulo 90 — Phoenix.Presence: O Vigia que Vê Tudo
A lenda diz que o Phoenix.Presence é um vigia. Ele vê quem está online. Ele vê quem entrou. Ele vê quem saiu. Ele replica essa informação para todos os nós. Se um nó cai, os outros sentem falta. Se um nó volta, os outros dão boas-vindas. O vigia nunca dorme. O vigia nunca esquece.
A verdade é que Phoenix.Presence fornece rastreamento de presença para processos e canais. É um behaviour que fornece recursos como buscar presenças para um tópico e lidar com diffs de eventos de join e leave em tempo real. Usar este módulo define um supervisor e permite que o módulo chamador implemente o behaviour Phoenix.Tracker, que inicia um processo tracker para lidar com informações de presença. Os tracker shards usam um protocolo de heartbeat e CRDT para replicar informações de presença através de um cluster de forma eventualmente consistente e livre de conflitos. Cada nó executa um pool de trackers e mudanças locais ao nó são replicadas através do cluster e tratadas localmente como um diff de mudanças.
A lenda diz que, na primeira vez que um programador usou Presence, ele perguntou: "Como isso funciona?" O instrutor respondeu: "Tracker shards. Heartbeat. CRDT."
O fato por trás da lenda: Phoenix.Presence fornece rastreamento de presença para processos e canais. Usa tracker shards com heartbeat e CRDT para replicar informações de presença de forma eventualmente consistente e livre de conflitos.
Gancho: O vigia vê. Mas há uma coisa que distribui mensagens: o Phoenix.PubSub.
Capítulo 91 — Phoenix.PubSub: O Megafone que Todos Ouvem
A lenda diz que o Phoenix.PubSub é um megafone. Você publica uma mensagem em um tópico. Todos os processos inscritos naquele tópico recebem a mensagem. Ninguém fica de fora. Ninguém ouve o que não devia. O megafone é justo.
A verdade é que Phoenix.PubSub é um serviço de Publisher/Subscriber em tempo real. O adapter padrão é o Phoenix.PubSub.PG2, que usa grupos de processos do Erlang para implementar o modelo PubSub onde um publisher pode enviar mensagens para muitos subscribers. O PG2 adapter usa o módulo :pg2 do Erlang (ou :pg em versões mais recentes). Em um cluster, o PubSub distribui mensagens entre os nós usando a distribuição Erlang. O Supabase Realtime, por exemplo, é um cluster Elixir globalmente distribuído que usa Phoenix.PubSub com o adapter PG2 padrão para implementar seus canais.
A lenda diz que, na primeira vez que um programador usou PubSub, ele perguntou: "Como o PubSub funciona?" O instrutor respondeu: "Você publica, eles ouvem."
O fato por trás da lenda: Phoenix.PubSub é um serviço de Publisher/Subscriber em tempo real. O adapter padrão é o PG2, que usa grupos de processos do Erlang. Em cluster, distribui mensagens entre nós usando a distribuição Erlang.
Gancho: O megafone transmite. Mas há uma coisa que registra nomes: o módulo global.
Capítulo 92 — :pg: O Grupo de Processos que Atravessa Nós
A lenda diz que o :pg é um grupo de processos. Mas não é um grupo comum. É um grupo que atravessa nós. Você entra no grupo. Outros processos entram no grupo. Todos se conhecem. Todos se falam. Se um morre, o grupo sente falta. Se um nasce, o grupo dá boas-vindas. O grupo nunca se desfaz. O grupo nunca se perde.
A verdade é que o módulo pg implementa grupos de processos distribuídos e nomeados. Uma mensagem pode ser enviada para um, alguns ou todos os membros do grupo. Um grupo de processos pode ser acessado por um nome comum. Por exemplo, se existe um grupo chamado foobar, pode haver um conjunto de processos (que podem estar localizados em nós diferentes) que são todos membros do grupo foobar. Não há funções especiais para enviar uma mensagem ao grupo. Em vez disso, funções cliente devem ser escritas com get_members/1 e get_local_members/1 para determinar quais processos são membros do grupo. Se um membro termina, ele é automaticamente removido do grupo. Process Groups implementam strong eventual consistency. A visão de associação do grupo pode divergir temporariamente. Por exemplo, quando processos em node1 e node2 entram concorrentemente, node3 e node4 podem receber atualizações em ordem diferente. Grupos são automaticamente criados quando qualquer processo entra, e removidos quando todos os processos saem.
A lenda diz que, na primeira vez que um programador usou :pg, ele perguntou: "Onde está o grupo?" O instrutor respondeu: "Em todo lugar. E em lugar nenhum. É distribuído."
O fato por trás da lenda: O módulo pg implementa grupos de processos distribuídos e nomeados. Uma mensagem pode ser enviada para um, alguns ou todos os membros do grupo. Process Groups implementam strong eventual consistency. Grupos são automaticamente criados quando qualquer processo entra, e removidos quando todos saem.
Gancho: O grupo atravessa nós. Mas há uma coisa que substitui o pg2: o :pg moderno.
Capítulo 93 — :pg2: O Módulo que Morreu para Dar Lugar ao :pg
A lenda diz que o :pg2 foi um grande general. Ele comandou grupos de processos. Ele os registrou. Ele os distribuiu. Mas ele tinha um defeito: ele não escalava. Ele ficava lento quando o exército crescia. E então, no OTP 23, os deuses da Ericsson decretaram: "O :pg2 está depreciado. Use o :pg." E o general caiu. E o :pg subiu. E o exército continuou marchando.
A verdade é que o módulo pg2 foi depreciado a partir do OTP 23 e removido no OTP 24. A recomendação oficial é substituir o uso de pg2 por pg. O pg tem uma API similar, mas com uma implementação que é muito mais escalável. O pg2 era usado para grupos de processos distribuídos, mas sua implementação não escalava bem. O Phoenix usava pg2 para agrupar canais, mas migrou para pg. A remoção do pg2 foi um marco na evolução da distribuição Erlang.
A lenda diz que, na primeira vez que um programador tentou usar pg2 no OTP 24, ele perguntou: "Onde está o pg2?" O instrutor respondeu: "Morreu. Use o pg."
O fato por trás da lenda: O módulo pg2 foi depreciado a partir do OTP 23 e removido no OTP 24. A recomendação é substituir por pg, que tem API similar mas implementação mais escalável.
Gancho: O general morreu. Mas há uma coisa que protege a distribuição: o TLS.
Capítulo 94 — TLS na Distribuição: A Armadura que a BEAM Veste
A lenda diz que a BEAM andava nua pela rede. Todos podiam ver suas mensagens. Todos podiam ler seus segredos. E então alguém disse: "Vista uma armadura." E a BEAM vestiu TLS. E as mensagens ficaram criptografadas. E os segredos ficaram seguros. E os man-in-the-middle choraram.
A verdade é que, por causa das limitações da autenticação baseada em cookie e para garantir a confidencialidade e integridade dos dados trocados entre nós, o uso de TLS é recomendado. Todos os nós Erlang participantes em um sistema distribuído devem usar este módulo de distribuição. A opção {verify, verify_peer} deve estar presente nas opções do cliente, juntamente com um {cacertfile, Path} apontando para o certificado da CA raiz usado para emitir os certificados dos nós. O uso de autenticação TLS mútua, usando um certificado de cliente e {verify, verify_peer} nas opções do servidor, é recomendado.
No entanto, uma vulnerabilidade recente (CVE-2026-48860) foi descoberta no módulo inet_tls_dist do Erlang/OTP. A função inet_tls_dist:check_ip/1, que impõe uma allowlist de LAN para distribuição Erlang sobre TLS, chama inet:sockname/1 em vez de inet:peername/1 para obter o endereço IP do peer. Como inet:sockname/1 retorna o endereço do socket local, tanto o IP local quanto o suposto IP do peer resolvem para o mesmo valor, fazendo com que a comparação da máscara de sub-rede sempre tenha sucesso, independentemente do endereço remoto real. Qualquer portador de um certificado TLS assinado por uma CA pode, portanto, contornar a restrição de LAN e obter acesso total à distribuição Erlang do nó, incluindo rpc:call/4 e code:load_binary/3.
A lenda diz que, na primeira vez que um programador ativou TLS, ele perguntou: "Agora está seguro?" O instrutor respondeu: "Agora está mais seguro. Mas mantenha o OTP atualizado."
O fato por trás da lenda: Erlang Distribution over TLS criptografa conexões de distribuição. A autenticação TLS mútua é recomendada. No entanto, a CVE-2026-48860 afeta a distribuição sobre TLS no OTP 26.0 até 29.0.2, 28.5.0.2 e 27.3.4.13.
Gancho: A armadura protege. Mas há uma coisa que mapeia nomes para portas: o EPMD.
Capítulo 95 — EPMD: O Cartório dos Nós que Ninguém Vê
A lenda diz que o EPMD é um cartório. Ele mapeia nomes de nós para portas. Ele fica rodando na sombra. Ele nunca aparece. Ele nunca reclama. Ele só registra. Ele só responde. Sem ele, os nós não se encontram. Sem ele, a distribuição não funciona. E se alguém o atacar, o cluster cai.
A verdade é que EPMD (Erlang Port Mapper Daemon) é um serviço que permite descoberta de nós por nome. Ele pode ser iniciado diretamente através do executável epmd, ou implicitamente pelo primeiro nó em um host (a menos que o argumento -start_epmd false seja passado para a VM). O EPMD normalmente escuta na porta 4369. O protocolo EPMD permite que clientes não autenticados procurem um nó por nome, bem como recuperem a lista completa de nós conhecidos. A resposta inclui a porta TCP na qual o protocolo de distribuição do nó pode ser alcançado. Executar o EPMD em uma rede não confiável, portanto, expõe informações sobre os clusters Erlang distribuídos conhecidos no host.
A lenda diz que, na primeira vez que um programador perguntou "O que é EPMD?", o instrutor respondeu: "É o cartório. E o cartório fica na sombra. Proteja-o."
O fato por trás da lenda: EPMD mapeia nomes de nós para portas. Escuta na porta 4369. O protocolo permite que clientes não autenticados recuperem a lista completa de nós conhecidos. Deve ser isolado de redes não confiáveis.
Gancho: O cartório registra. Mas há uma coisa que explica os limites: o Teorema CAP.
Capítulo 96 — CAP: O Teorema que a BEAM Ignora (ou Não)
A lenda diz que, quando os aliens criaram a BEAM, eles leram o Teorema CAP e disseram: "Vamos escolher AP." E assim fizeram. A maioria das bibliotecas distribuídas do Elixir fica do lado AP do Teorema CAP.
A verdade é que o Horde, por exemplo, é eventualmente consistente, o que significa que pode garantir disponibilidade e tolerância a partição. Quando a associação ao cluster do Horde é constante (ou seja, não há nós sendo adicionados ou removidos), o Horde também garante consistência. Quando um nó é adicionado ou removido do cluster, há uma pequena janela na qual isso não é verdade. O Horde escolhe o lado AP do Teorema CAP.
No entanto, existe o Paxtor, uma biblioteca Elixir para construir sistemas distribuídos CP (Consistent and Partition-tolerant) no BEAM. O Paxtor é baseado no PaxosKV, que fornece uma camada de consenso baseada no algoritmo Basic Paxos.
A lenda diz que, na primeira vez que um programador ouviu falar do CAP, ele perguntou: "Qual lado é melhor?" O instrutor respondeu: "Depende do que você não pode perder."
O fato por trás da lenda: O Horde é eventualmente consistente, garantindo disponibilidade e tolerância a partição (AP), mas também consistência quando a associação ao cluster é constante. O Paxtor é uma biblioteca CP que usa Paxos.
Gancho: O teorema explica. Mas há uma coisa que a BEAM faz melhor: tolerância a falhas.
Capítulo 97 — Horde: O Supervisor que Não Conhece Fronteiras
A lenda diz que o Horde é um supervisor. Mas não é um supervisor comum. Ele supervisiona através de nós. Ele distribui processos. Ele mantém um registro. Ele é construído sobre DeltaCrdt. Ele é eventualmente consistente. Ele nunca perde um processo. Ele nunca deixa um nó sozinho.
A verdade é que Horde é composto por Horde.Supervisor, um supervisor distribuído, e Horde.Registry, um registro distribuído. Horde é construído sobre DeltaCrdt. Como Horde é construído sobre CRDTs, ele é eventualmente consistente (em vez de imediatamente consistente), embora sincronize seu estado com seus vizinhos de forma bastante agressiva. A associação ao cluster no Horde é totalmente dinâmica; nós podem ser adicionados e removidos a qualquer momento e o Horde continuará operando conforme esperado. Horde.Supervisor também usa um anel de hash para limitar quaisquer condições de corrida a momentos em que a associação ao cluster está mudando. Horde.Registry é API-compatível com o Registry do Elixir, embora ainda não suporte a opção keys: :duplicate. Se um nó falha (ou se torna inalcançável), o Horde.Supervisor redistribuirá os processos entre os nós restantes. Você pode escolher o que fazer em caso de partição de rede especificando :distribution_strategy. Horde.UniformDistribution (o padrão) distribui processos usando um mecanismo de hash entre todos os nós alcançáveis. Em caso de partição de rede, ambos os lados da partição continuarão a operar. Horde.UniformQuorumDistribution opera da mesma forma, mas desliga se menos da metade do cluster estiver alcançável.
A lenda diz que, na primeira vez que um programador usou Horde, ele perguntou: "O que acontece se um nó cair?" O instrutor respondeu: "Os processos se mudam."
O fato por trás da lenda: Horde é um supervisor distribuído e registro construído sobre DeltaCrdt. É eventualmente consistente, garantindo disponibilidade e tolerância a partição. Usa anel de hash para limitar condições de corrida. Se um nó cai, os processos são redistribuídos. UniformQuorumDistribution desliga se menos da metade do cluster estiver alcançável.
Gancho: O supervisor distribui. Mas há uma coisa que coordena nomes globalmente: o módulo global.
Capítulo 98 — O Módulo global: O Cartório dos Nomes Distribuídos
A lenda diz que o módulo global é um cartório. Ele registra nomes. Ele notifica todos os nós. Ele monitora nós. Ele mantém a rede totalmente conectada. Ele é o cartório dos nomes distribuídos. Ele nunca perde um nome. Ele nunca deixa um nó sozinho.
A verdade é que o módulo global fornece registro de nomes globalmente distribuído. Ele consiste em serviços para: registro global de nomes, locks globais, e manutenção da rede totalmente conectada. Esses serviços são controlados através do processo global_name_server, que existe em cada nó. O global é iniciado automaticamente quando um nó é iniciado. A capacidade de registrar nomes globalmente é um conceito central na programação de sistemas Erlang distribuídos. Um nome registrado é um alias para um process identifier (pid). O global name server monitora pids globalmente registrados. Se um processo termina, o nome é globalmente desregistrado. Os nomes registrados são armazenados em tabelas de nomes globais replicadas em cada nó. Não há ponto de armazenamento central. A tradução de um nome para um pid é rápida, pois é sempre feita localmente.
A partir do OTP 25, o global irá, por padrão, prevenir partições sobrepostas devido a problemas de rede, desconectando ativamente de nós que relatam ter perdido conexões com outros nós. Isso fará com que partições totalmente conectadas se formem em vez de deixar a rede em um estado com partições sobrepostas. Uma rede de partições sobrepostas pode causar o estado interno do global se tornar inconsistente. Tal inconsistência pode permanecer mesmo depois que tais partições forem reunidas para formar uma rede totalmente conectada novamente. É fortemente recomendado não desabilitar esta correção. Note que esta correção deve ser habilitada em todos os nós da rede para funcionar corretamente.
A lenda diz que, na primeira vez que um programador usou global, ele perguntou: "Onde está o nome?" O instrutor respondeu: "No cartório. E o cartório está em todo lugar."
O fato por trás da lenda: O módulo global fornece registro de nomes globalmente distribuído. A partir do OTP 25, previne partições sobrepostas desconectando ativamente nós que perderam conexões. A correção deve ser habilitada em todos os nós.
Gancho: O cartório registra. Mas há uma coisa que testa partições: o Schism.
Capítulo 99 — Schism: O Feiticeiro que Parte a Rede
A lenda diz que o Schism é um feiticeiro. Ele parte a rede. Ele simula netsplits. Ele testa partições. Ele usa um truque com cookies. Ele nunca erra. Ele nunca deixa uma partição passar despercebida.
A verdade é que Schism é uma ferramenta de teste de partição para Elixir. Ele fornece uma API simples para testar partições entre nós BEAM. O motivo de existência do Schism é testar netsplits entre BEAMs de forma rápida e fácil, e ele usa um truque rudimentar com cookies para atingir esse objetivo. Schism é usado em conjunto com ferramentas como local_cluster e propcheck. Ele não é recomendado para uso em produção. Schism não testa conexões TCP falhas, intercalação de mensagens, condições de corrida, clock skew, corrupção, ou qualquer um dos outros problemas que você verá em um sistema distribuído.
A lenda diz que, na primeira vez que um programador usou Schism, ele perguntou: "O que é um netsplit?" O instrutor respondeu: "É quando a rede se parte ao meio. E o Schism te ajuda a testar isso."
O fato por trás da lenda: Schism é uma ferramenta de teste de partição para Elixir. Usa um truque com cookies. Não é recomendado para produção. Não testa conexões TCP falhas, intercalação de mensagens, condições de corrida, clock skew ou corrupção.
Gancho: O feiticeiro parte. Mas há uma coisa que lida com partições: o global_supervisor.
Capítulo 100 — O Fim do Tomo VI: A Batalha que Nunca Termina
A lenda diz que, no fim de tudo, quando todos os tomos forem escritos, a batalha continuará. A rede se partirá. Os nós cairão. Os processos reiniciarão. E a BEAM continuará lutando.
A verdade é que a distribuição no BEAM é embutida no runtime, não uma biblioteca acoplada. Nós Erlang se conectam via TCP/IP e compartilham um cookie para autenticação. Libcluster forma clusters automaticamente. O Teorema CAP se aplica: a maioria das bibliotecas do Elixir é AP; o Paxtor é CP. A tolerância a falhas da BEAM é um dos seus pontos mais fortes. Supervisores formam árvores de supervisão. GenServer encapsula estado. O scheduler usa reduções para preempção. Horde é um supervisor distribuído construído sobre DeltaCrdt. O módulo global registra nomes globalmente e, a partir do OTP 25, previne partições sobrepostas. Schism testa netsplits. Net splits parciais são um problema não solucionável com a distribuição Erlang nativa. global_supervisor lida com partições. Phoenix.PubSub distribui mensagens entre nós. Phoenix.Presence rastreia presenças. Partisan oferece uma alternativa à distribuição nativa. A supervisão distribuída não é nativa e requer bibliotecas externas. Pogo, Chosen, Sworm e outras bibliotecas oferecem soluções para supervisão distribuída. A segurança da distribuição depende de cookies e, idealmente, TLS, mas vulnerabilidades como a CVE-2026-48860 mostram que nem o TLS está imune.
Este foi o Tomo VI — A Batalha. Cem capítulos. Uma batalha. Mil processos. E um brasileiro que ouviu um sussurro.
No próximo tomo, As Ferramentas, vamos explorar Dialyzer, Credo, Benchee, Observer, ExDoc, e todas as ferramentas que tornam o desenvolvimento Elixir mais seguro e mais divertido.
Até lá.
O fato por trás da lenda: A distribuição no BEAM é embutida no runtime. Nós Erlang se conectam via TCP/IP e compartilham um cookie. Libcluster forma clusters. O Teorema CAP se aplica. A tolerância a falhas da BEAM é um dos seus pontos mais fortes. Horde, global, Schism, Partisan, Pogo, Chosen, Sworm, e muitas outras bibliotecas lidam com os desafios da distribuição. A segurança da distribuição depende de cookies e, idealmente, TLS.
Agora, sério: A distribuição no BEAM é embutida no runtime. Nós Erlang se conectam via TCP/IP e compartilham um cookie. Libcluster forma clusters. O Teorema CAP se aplica. A tolerância a falhas da BEAM é um dos seus pontos mais fortes. Horde, global, Schism, Partisan, Pogo, Chosen, Sworm, e muitas outras bibliotecas lidam com os desafios da distribuição. A segurança da distribuição depende de cookies e, idealmente, TLS. As capivaras quânticas não são reais — mas deveriam ser. Este artigo é uma fantasia satírica baseada em fatos. Mantenha o aviso para não enganar ninguém.
Top comments (0)