O que é presença (status online)?

Atualizado em: agosto de 2026

Presença é um sinal em tempo real que indica se um usuário está online, ausente ou offline, mantido fresco por conexões e heartbeats. A bolinha verde é uma interface enganosamente simples sobre um problema distribuído genuinamente difícil: o servidor precisa inferir a ausência — dispositivos raramente anunciam a própria morte — e depois transmitir cada inferência para todos que estão observando, na escala de uma lista de contatos. Padronizado muito antes do chat moderno, nas stanzas de presença do XMPP, o padrão tem fundamentos que não mudaram desde então.

Principais pontos

PerguntaResposta
Os estadosonline · ausente/ocioso · offline — mais overrides definidos pelo usuário (não perturbe)
O mecanismoEscritas de heartbeat + expiração por TTL; eventos de conexão como caminho rápido
Os númerosHeartbeat de ~30 s · timeout de offline em 2–3× o intervalo · 30–60 s de carência contra oscilação
O companheiroVisto por último — o timestamp durável por trás da bolinha efêmera
A parte difícilFan-out: N observadores × M mudanças de status, multiplicados pelo seu sucesso

O contrato do heartbeat

O padrão inteiro cabe em uma troca:

cliente     a cada 30 s:  save { status: "online", lastActiveAt: now }
servidor    a cada 60 s:  varredura — lastActiveAt mais velho que 90 s?  → status: "offline"
                          (TTL = 2–3 × intervalo do heartbeat)
observador  status = "online"   → bolinha verde
            status = "offline"  → "visto às 12:41"  ← lastActiveAt, a parte durável

O mesmo contrato como código de SDK — heartbeat para fora, subscription para dentro:

// JavaScript / Node.js — Back4app JS SDK
// Presence: heartbeat your own status, subscribe to your contacts'
const heartbeat = () =>
  myPresence.save({ status: 'online', lastActiveAt: new Date() });
await heartbeat();
setInterval(heartbeat, 30_000); // server sweeps offline at 2–3× this

const contacts = new Parse.Query('Presence');
contacts.containedIn('user', myContactIds);
const sub = await contacts.subscribe();
sub.on('update', (p) => setStatus(p.get('user'), p.get('status')));

Eventos de conexão vs. TTL de heartbeat

Os dois modelos de detecção, comparados com honestidade — nenhuma página de ranking faz isso em uma tabela só:

Ciclo de vida da conexãoHeartbeat + TTL
Sinal de onlineSocket abertoHeartbeat fresco dentro da janela
Sinal de offlineEvento/frame de fechamentoExpiração do TTL — sem heartbeat por 2–3 intervalos
Velocidade de detecçãoInstantânea no fechamento limpoAtraso limitado (até o timeout)
Falhas silenciosasNão pega — queda de energia não envia frame de fechamentoPega — o silêncio é o sinal
Estado no servidorRastreamento por conexãoEscritas sem estado em um store com TTL
Como falhaUsuários “online” zumbisFalso “offline” breve em batidas perdidas

O protocolo WebSocket em si ensina a lição: ele traz frames de controle ping/pong justamente porque o TCP não revela um par que sumiu, e sua taxonomia de close codes reserva o 1006 para “fechamento anormal — nenhum frame de fechamento recebido”, o caso zumbi. Presença de produção, portanto, empilha os dois modelos: eventos de conexão para transições instantâneas, expiração de heartbeat como a verdade que pega o que os eventos deixam passar.

A máquina de estados

Máquina de estados de presença com período de carênciaUm usuário vai de offline para online ao conectar ou ao enviar heartbeat, de online para ausente quando o app vai para segundo plano ou a entrada fica ociosa, e caminha para offline por um período de carência que começa na desconexão ou em batidas perdidas e é cancelado se o usuário reconectar antes de ele terminar.

conecta / heartbeat

aba oculta · entrada ociosa

atividade retoma

desconexão ou batidas perdidas

desconexão ou batidas perdidas

reconecta a tempo

timer dispara → publica

offline
(serve o visto por último)

online

ausente

período de carência
30–60 s

Um usuário vai de offline para online ao conectar ou ao enviar heartbeat, de online para ausente quando o app vai para segundo plano ou a entrada fica ociosa, e caminha para offline por um período de carência que começa na desconexão ou em batidas perdidas e é cancelado se o usuário reconectar antes de ele terminar.

Dois refinamentos distinguem as implementações bem-acabadas. Ausente é detectado no cliente: o servidor não enxerga uma aba em segundo plano, mas o navegador sim — a Page Visibility API sinaliza abas ocultas, listeners de entrada sinalizam ociosidade, e um sinal de offline em melhor esforço no fechamento da aba viaja pela Beacon API. Offline tem debounce: o estado de carência existe porque conexões móveis oscilam — publique “offline” a cada túnel e elevador e a lista de contatos de cada observador pisca em solidariedade. Atrase o anúncio, cancele na reconexão, e a oscilação colapsa em quietude. Mais uma distinção que vale roubar do protocolo que formalizou presença: presença computada (online, pela conexão) versus status definido pelo usuário (não perturbe) — o segundo sempre ganha o merge.

Efêmero por design

Presença é um cache da realidade, não um registro: um status que chega atrasado é pior que status nenhum — o “online” de ontem é mentira hoje. Esse princípio guia as escolhas de implementação: os status vivem em stores rápidos com TTL em vez de tabelas duráveis, nunca são enfileirados para entrega offline e são o primeiro dado descartado sob backpressure. Só o lastActiveAt merece persistência. Indicadores de digitação são o princípio no extremo — micro-presença escopada a uma conversa, expirando em segundos, com debounce no remetente e descartada em vez de retentada; se “Ada está digitando…” não pode chegar agora, não deveria chegar nunca.

O problema do fan-out

O muro de escala da presença é multiplicação, não armazenamento. Um exemplo real: 100.000 usuários simultâneos, cada um visível para 50 contatos, cada um mudando de estado modestos 20 vezes por hora — isso dá 100.000 × 50 × 20 = 100 milhões de eventos de presença por hora para entregar, vindos de uma feature que guarda uma linha pequena por usuário. As alavancas, na ordem em que se puxa: inscreva-se de forma estreita — observe os usuários que estão na tela (a lista de conversas abertas), não o grafo inteiro de contatos; puxe, não empurre, a cauda longa — busque o visto por último quando um perfil abrir, em vez de transmiti-lo; limite a transmissão em grupos — acima de algumas centenas de membros, mostre presença na interação, não para a lista toda; e agrupe transições para que um usuário oscilando custe um evento com debounce, não trinta. O próprio fan-out roda sobre a maquinaria padrão de pub/sub — presença é o caso de canto at-most-once desse padrão, em que descartar um evento velho é feature.

Vários dispositivos e privacidade

Um usuário, três dispositivos, uma bolinha — presença por usuário é um merge sobre presença por dispositivo. Rastreie o heartbeat de cada dispositivo separadamente; o usuário está online enquanto qualquer um estiver, e a política de merge é “o mais disponível vence”: online no celular ganha de ocioso no desktop, e o não-perturbe de qualquer dispositivo sobrepõe os demais. O visto por último reporta o dispositivo mais recente. Privacidade é a outra metade do design, e a metade que os blogs de engenharia pulam apesar de ser o que os usuários mais perguntam: regras de visibilidade (todos / contatos / ninguém), reciprocidade (esconda o seu, perca a visão do dos outros) e visto por último grosseiro (“recentemente” em vez de horário). Aplique as regras nas permissões da camada de dados — presença é dado comportamental, e um “online às 3 da manhã” vazado é uma divulgação real.

Casos de uso comuns

  • Chat e mensageria — a bolinha verde canônica, o visto por último e os indicadores de digitação.
  • Ferramentas de colaboração — quem está no documento, presença de cursor, barras laterais de “ativos agora”.
  • Suporte e marketplaces — roteamento por disponibilidade de atendente, sinais de confiança do tipo “vendedor online”.
  • Multiplayer e social — lobbies, listas de amigos, atalhos para entrar junto com um amigo.
  • Ferramentas de força de trabalho — estados de disponibilidade alimentando roteamento e dashboards de status.

Como você deveria construir presença? Matriz de decisão

FeatureMecanismo
Bolinha verde nos contatosHeartbeat + store com TTL, subscription de live query nos usuários visíveis
Transições instantâneas em um chat abertoEventos de conexão como caminho rápido no socket
Visto por últimoTimestamp a cada heartbeat; busca sob demanda
Detecção de ausênciaNo cliente: listeners de visibilidade e ociosidade, reportados no heartbeat
Indicador de digitaçãoMicro-eventos por conversa, TTL de segundos, nunca persistidos
Presença em um grupo de 5.000 membrosNão transmita — mostre na interação, limite a lista

Limitações e trade-offs

  • Presença é probabilística. Entre heartbeats, a bolinha é um palpite; sistemas honestos abraçam a defasagem limitada em vez de fingir verdade instantânea.
  • Frescor custa escritas. Reduzir o intervalo de heartbeat pela metade dobra a carga de escrita de toda a população online — velocidade de detecção se compra em throughput.
  • Fan-out escala com o sucesso. A feature é barata com 1.000 usuários e vira projeto de arquitetura com 10 milhões; defina o escopo das subscriptions antes que o crescimento force.
  • Oscilação é inerente. Redes móveis garantem churn de reconexão; sem debounce, a presença amplifica ruído de rede em ruído de interface.
  • O formato é de vigilância. Padrões de horário online revelam sono, trabalho e hábitos; controles de visibilidade e aplicação na camada de permissões são requisitos, não melhorias.

Presença no Back4app

O Back4app é uma plataforma open-source de Backend as a Service (BaaS) que combina banco de dados gerenciado, APIs REST e GraphQL geradas automaticamente, autenticação, armazenamento de arquivos e funções serverless com Cloud Code. Os blocos de construção acima mapeiam um a um: uma classe Presence guarda status e lastActiveAt; o heartbeat é um save periódico (as abas de código); observadores mantêm uma subscription de Live Query nos contatos que estão na tela, recebendo atualizações por push sobre a frota gerenciada de WebSockets da plataforma; um job agendado no Cloud Code é a varredura de TTL, virando linhas velhas para offline e disparando o debounce; e permissões de classe mais ACLs implementam as regras de visibilidade na camada de dados, onde elas devem morar. Nada sob medida para operar — presença vira um exercício de modelagem de dados sobre infraestrutura que o backend já roda.

Perguntas frequentes

O que é um sistema de presença?

Um serviço que rastreia se cada usuário está online, ausente ou offline e transmite as mudanças, em tempo real, para quem tem permissão de vê-las. Por baixo do capô: conexões persistentes ou heartbeats periódicos escrevendo em um store rápido em memória, com as mudanças de status espalhadas por pub/sub.

Como funciona o "visto por último"?

O servidor grava um timestamp a cada heartbeat e a cada desconexão. Enquanto você está online, o status ao vivo é servido; quando você fica offline, o último timestamp gravado responde no lugar dele. É a única peça durável de um sistema no resto efêmero — o status expira, o visto por último permanece.

Qual intervalo de heartbeat usar em presença?

Trinta segundos é o padrão comum em produção, com o timeout de offline em duas a três vezes o intervalo (60 a 90 segundos). Intervalos mais curtos reduzem o atraso de detecção, mas multiplicam a carga de escrita linearmente com sua população online; o intervalo também precisa ficar abaixo dos timeouts de idle da infraestrutura, ou os proxies matam as conexões quietas antes.

Detecção por conexão ou por heartbeat — qual é melhor?

As duas, para falhas diferentes. Eventos de conexão (abrir/fechar) dão transições instantâneas, mas não pegam mortes silenciosas — um aparelho que perde energia não envia frame de fechamento e deixa uma conexão zumbi. A expiração do heartbeat limita essa defasagem ao custo de um atraso de detecção. Sistemas de produção usam eventos de conexão como caminho rápido e o TTL do heartbeat como fonte da verdade.

Como evitar que o status online fique piscando?

Faça debounce da transição para offline: na desconexão, inicie um timer de carência — comumente de 30 a 60 segundos — e cancele se o usuário reconectar, publicando "offline" só quando o timer disparar. Usuários em elevadores e túneis de metrô reconectam o tempo todo; sem o período de carência, toda lista de contatos em que eles aparecem pisca junto.

Como a presença escala para milhões de usuários?

Respeitando a matemática do fan-out: toda mudança de status precisa chegar a todo observador, então N contatos vezes M transições explode rápido. As alavancas são um store em memória com TTL para o status, inscrever-se apenas nos usuários visíveis (a lista de conversas abertas, não a agenda inteira), buscar o visto por último sob demanda em vez de empurrá-lo, e limitar a transmissão de status em grupos grandes.

Como funciona presença com vários dispositivos?

Rastreie uma conexão ou heartbeat por dispositivo e faça merge: o usuário está online enquanto qualquer dispositivo estiver, e offline só quando o último se cala. A política de merge usual é "o mais disponível vence" — online no celular ganha de ocioso no desktop — com o visto por último tirado do dispositivo mais recente.

Dá para esconder o status online?

Deveria dar — visibilidade é feature de produto, não detalhe posterior: regras como todos, só contatos ou ninguém, normalmente com reciprocidade (esconda o seu e você deixa de ver o dos outros). Dados de presença são dados comportamentais; defina quem pode observar quem no modelo de permissões, não na interface.

Termos relacionados

Compare com

Leitura adicional

Pronto para construir seu backend?

Comece seu projeto no Back4app em minutos — banco de dados, autenticação, APIs e Cloud Code incluídos. Sem cartão de crédito.

Escrito e revisado por Back4app Engineering, Back4app Engineering · Publicado em 2026-08-25