Sistema de Claps Otimista: Replicando a UX do Medium
Como construir um sistema de applause/claps igual ao Medium com otimizações agressivas que reduzem 85% das operações no banco de dados.
Sistema de Claps Otimista: Replicando a UX do Medium#
Acabei de implementar um sistema de claps igual ao Medium no meu portfólio. O resultado? 85% menos operações no Redis e uma UX indistinguível do original!
O Desafio#
O Medium permite até 50 "claps" por artigo com feedback instantâneo. O desafio era replicar essa experiência sem sobrecarregar o servidor.
Problemas do Sistema Simples:#
- 1 requisição por clap = 50 requisições potenciais
- Latência perceptível entre clap e feedback
- Rate limiting complexo
- UX quebrada em conexões lentas
A Solução: Otimismo Inteligente#
1. Updates Otimistas#
const addClap = useCallback(() => {
// Atualiza UI instantaneamente
const newOptimistic = {
total: optimistic.total + 1,
userClaps: optimistic.userClaps + 1,
hasClapped: true,
}
setOptimistic(newOptimistic)
saveToCache(newOptimistic)
// Sincroniza em background
debouncedSync()
}, [optimistic, debouncedSync])
2. Batching Inteligente#
O sistema agrupa claps em lotes e espera 2 segundos de pausa antes de sincronizar:
// Detecta burst de claps
if (burstCountRef.current >= 5) {
syncImmediately() // Sync imediato para evitar perda
} else {
debounceSync(2000) // Aguarda pausa
}
3. Cache Estratificado#
Três níveis de cache:
- UI State: Instantâneo, sempre atualizado
- localStorage: 2min TTL, sobrevive a reloads
- Redis: Backend cache com TTL variável
4. Estados Visuais Avançados#
Progression System (0-50 claps):
- 1-10: Coração se enche gradualmente
- 11-25: Efeito pulsante vermelho
- 26-40: Múltiplos corações flutuantes
- 41-50: Modo celebration com ⚡
5. Animações de Micro-interação#
// Burst effect em claps rápidos
{rapidClaps > 0 && (
<motion.div
className="floating-indicator"
animate={{ y: [-10, 0], opacity: [0, 1, 0] }}
>
+{rapidClaps}
</motion.div>
)}
Resultados Mensuráveis#
Performance:#
- Antes: ~98 reads + 41 writes para 5 likes
- Depois: ~15 reads + 8 writes para 50 claps
- Redução: 85% menos operações
UX:#
- Resposta UI: < 16ms (60fps)
- Sync transparente em background
- Fallback graceful para dados stale
- Zero interrupções na experiência
Otimizações Redis:#
Pipeline Otimizado:
// Batch de 10 claps = 1 operação
pipeline.incrby('claps:post:123:total', 10)
pipeline.incrby('claps:post:123:user:abc', 10)
pipeline.incrby('claps:ratelimit:abc:2024-03-20', 10)
vs Sistema Antigo:
// 10 claps = 60 operações (6 por clap)
for (let i = 0; i < 10; i++) {
pipeline.incr('likes:post:123:total')
pipeline.incr('likes:post:123:user:abc')
pipeline.incr('likes:ratelimit:abc:2024-03-20')
pipeline.expire(key1, ttl)
pipeline.expire(key2, ttl)
pipeline.expire(key3, ttl)
}
Lições Aprendidas#
1. Otimismo Funciona#
Updates otimistas + sync em background = UX perfeita. O usuário nunca percebe latência.
2. Batching é Poderoso#
Agregar operações reduz drasticamente a carga no servidor sem impactar UX.
3. Cache em Camadas#
Múltiplos níveis de cache criam redundância e performance.
4. Visual Feedback é Crucial#
Animações e estados visuais mantêm o usuário engajado durante operações async.
Próximos Passos#
- Analytics: Métricas de engajamento por post
- Personalização: Efeitos visuais customizáveis
- Social: Sistema de leaderboards
- Mobile: Haptic feedback para toque
O sistema está production-ready e pode ser facilmente adaptado para qualquer aplicação que precise de interações frequentes com feedback instantâneo.
Resultado: UX igual ao Medium com infraestrutura 85% mais eficiente! 🚀