04 / Journal
Technology / Oct 2026
Uma bolinha verde pode ser um problema de arquitetura
O que construir presença no PING me ensinou sobre sincronização, múltiplos dispositivos e a diferença entre mostrar um status e representar a realidade.
Published
October 26, 2026
READ TIME
5 min read
Quando desenhamos uma lista de amigos, a presença costuma parecer uma das funcionalidades mais simples do produto.
Uma bolinha verde para quem está online. Cinza para quem saiu. Talvez amarelo para ausente. O componente cabe em poucas linhas; o requisito, não.
No PING, essa pequena informação virou uma das melhores maneiras de entender como um detalhe visual pode atravessar toda a arquitetura. Porque a bolinha não está dizendo apenas que um servidor recebeu um evento. Ela está fazendo uma promessa: há uma pessoa disponível do outro lado.
Quando essa promessa falha, a experiência começa a perder confiança.
“Online” é uma decisão de produto antes de ser uma condição técnica
Uma aba aberta é suficiente para considerar alguém online? E se o computador estiver bloqueado? E se houver uma chamada ativa em segundo plano? E quando a pessoa escolhe aparecer offline?
Essas perguntas não se resolvem com um isOnline: true no banco. Precisam de semântica.
No PING, existem estados como online, ausente, ocupado e offline. Cada um comunica uma expectativa diferente. Mas a disponibilidade exibida também pode depender do dispositivo, da sessão e da escolha deliberada da pessoa.
Por isso é importante separar pelo menos três ideias: conectividade, atividade e visibilidade. Alguém pode estar conectado e inativo. Pode estar ativo em uma chamada, mesmo sem interagir com a janela. E pode estar conectado, mas preferir não ser exibido como disponível.
Misturar essas dimensões produz bugs que parecem aleatórios, embora tenham origem numa modelagem confusa.
O tempo real não elimina o tempo
Em aplicações distribuídas, “agora” não é um instante universal. Um evento chega ao servidor, outro chega ao cliente, e uma reconexão pode mudar a ordem em que o usuário percebe as coisas.
Imagine uma pessoa fechando o notebook sem encerrar a aplicação de maneira limpa. Se a interface dos amigos depender apenas do último evento de desconexão, ela poderá continuar online por mais tempo do que deveria. Se o sistema for agressivo demais ao marcar ausência, oscilações momentâneas farão o status piscar.
O mesmo acontece quando há várias sessões abertas. Uma aba perde conexão enquanto o aplicativo desktop continua ativo. Quem representa o estado final daquela pessoa?
A solução não é simplesmente disparar mais eventos. É definir qual informação tem autoridade, quanto tempo ela vale e como o estado é reconciliado quando a conexão volta. Heartbeats, expiração, atualização otimista e sinais de atividade são ferramentas possíveis, mas só ajudam quando seguem um contrato coerente.
Para o usuário, o indicador deve ser estável o bastante para transmitir confiança e responsivo o bastante para ser útil. Esse equilíbrio é tanto engenharia quanto UX.
O caso do AFK deixou isso muito concreto
Um dos fluxos que desenvolvi no PING envolve a identificação de inatividade e a movimentação para um canal AFK nos Espaços. No desktop, é possível usar informações de inatividade do sistema operacional por meio da ponte entre o Electron e a aplicação. Em clientes web, esse tipo de informação não possui a mesma confiabilidade.
Em teoria, parecia direto: detectar um período de inatividade e agir. Na prática, surgiram problemas quando a noção de inatividade da interface não correspondia ao comportamento real da pessoa. Um usuário podia estar participando de uma conversa, sem mover o mouse, e ainda assim continuar presente socialmente.
Havia outra sutileza: atualizar a interface web hospedada não atualiza automaticamente os recursos nativos presentes numa versão antiga do aplicativo desktop. Uma diferença entre renderer e preload pode fazer a mesma funcionalidade ter comportamentos diferentes dependendo da versão instalada.
Isso me forçou a tratar sinais desconhecidos como desconhecidos — e não como prova de ausência. Não receber uma informação confiável é diferente de receber uma confirmação de inatividade.
A especificação do fluxo, os testes e os ajustes de integração passaram a importar tanto quanto a regra de cinco minutos que alguém configurava na tela.
A interface precisa admitir estados intermediários
Há um impulso recorrente no front-end de representar tudo como binário: conectado ou desconectado, carregando ou pronto, presente ou ausente.
Só que produtos de comunicação vivem em transições. Uma pessoa pode estar entrando no canal, reconectando a sessão ou aguardando a confirmação de que sua presença foi reconhecida pelo restante do Espaço.
Quando escondemos tudo isso atrás de um único spinner, o produto parece lento mesmo que parte da operação já tenha acontecido. Quando mostramos a pessoa como conectada antes de validar a participação efetiva, o produto parece rápido, mas pode mentir.
Esse é um problema que ainda exige refinamento: reduzir a latência percebida sem antecipar estados que o sistema ainda não confirmou.
Prefiro pensar em uma sequência clara: intenção de entrar, conexão em andamento, presença confirmada. Cada estado tem um feedback adequado, um caminho de recuperação e um limite sobre o que a interface pode afirmar.
O custo de uma abstração aparentemente conveniente
Em algum momento é tentador criar um único objeto global de presença e deixar cada componente interpretá-lo como quiser. A home lê de um jeito, a lista de amigos de outro e o painel de voz aplica suas próprias exceções.
Isso funciona até os comportamentos começarem a divergir.
Uma abordagem melhor é explicitar o contrato: quais estados existem, qual a origem de cada sinal, o que significa atividade em cada contexto e quais transições são permitidas. A interface consome uma representação coerente, mas não precisa carregar regras de negócio espalhadas em componentes visuais.
Esse raciocínio também evita uma armadilha: transformar um caso especial em regra global. Estar sem mexer no mouse não deveria, por padrão, desfazer uma participação legítima em áudio.
O aprendizado vai além do PING
Toda vez que vejo uma bolinha verde agora, lembro que ela não representa apenas um estado de CSS. Representa uma decisão sobre tempo, confiança e comportamento humano.
Em dashboards, a mesma discussão aparece em indicadores “ao vivo”. Em sistemas colaborativos, aparece em cursores e editores simultâneos. Em ferramentas operacionais, aparece em status de processamento. A interface pode ser mínima, mas o contrato que a sustenta precisa ser preciso.
Construir presença no PING me ensinou que o objetivo não é exibir atualizações o mais rápido possível. É fazer com que a informação continue verdadeira o suficiente para orientar uma ação.
No fim, uma bolinha verde só parece simples quando toda a complexidade ao redor foi bem resolvida.
Este texto faz parte de uma série sobre a construção do PING. No próximo, vou abordar por que o sucesso de uma chamada não termina quando os dois participantes se conectam.
Share on
WEEKLY NOTE / NEWSLETTER
Enjoyed this insight?
Get weekly reflections on technology, product, and execution decisions.
No spam. Only content worth opening.
Related notes
03