En Gruppo Mai Più construimos productos digitales para negocios reales. Uno de ellos es HotelManager, un sistema para hoteles donde la recepción trabaja en una app local y el dueño puede ver parte de la operación desde la nube.
Una decisión chica en apariencia terminó siendo importante: ¿cada cuánto sincronizamos el hotel con la nube sin frenar la operación local?
Al principio parecía discutible desde los dos lados. Si era demasiado corto, podía ser caro a escala. Si era demasiado largo, el panel web podía sentirse lento.
El número que quedó en el centro fue 5 segundos. No por magia, sino por una decisión de producto: aceptar unos segundos de demora para tener un sistema simple, resistente y fácil de operar.
En una frase: la recepción trabaja en tiempo real de forma local; la nube se actualiza en pocos segundos.
El principio
HotelManager está pensado primero para el mostrador.
Un check-in, un checkout, un cobro o un cambio de habitación no pueden depender de internet. Por eso el sistema principal corre dentro del hotel.
La app de escritorio habla con un servicio local, que escribe en una base local cifrada1. La nube no está en el camino crítico de la operación diaria.
La nube tiene otro rol: darle al dueño visibilidad, configuración remota, auditoría, salud de la sincronización y herramientas de gestión. No buscamos milisegundos perfectos; buscamos operación local sin fricción y una nube lo bastante fresca para decidir.
Los datos de la sincronización
Cuando decimos "5 segundos", estamos simplificando. El sistema tiene varios relojes.
| Capa | Reposo | Con trabajo | Dato clave |
|---|---|---|---|
| Eventos hotel a nube | 5s | 100ms2 | Lotes de hasta 100 eventos |
| Comandos nube a hotel | 3s | 100ms2 | Lotes de hasta 50 comandos |
| App de escritorio | 8s | Al volver a estar visible | No refresca si la ventana está oculta |
| Panel web | 20s | 3s | Va rápido mientras hay trabajo pendiente |
| Fallas de sincronización | Backoff progresivo3 | Hasta 5 min | Evita tormentas de reintentos |
Lo más importante está en la primera fila: si el hotel no tiene eventos nuevos, el proceso de publicación no manda una solicitud vacía a la nube. Solo revisa la base local y vuelve a dormir.
Eso evita una confusión común. No significa que cada hotel esté enviando datos cada 5 segundos para siempre. Si no cambió nada, no hay nada que publicar.
Qué pasa cuando algo cambia
La sincronización tiene dos direcciones.
Cuando el servidor local guarda un cambio, también guarda un evento en una cola de salida4.
Un proceso en segundo plano revisa esa cola. Si hay eventos, los manda a la nube. Si encontró trabajo, vuelve a revisar en 100ms para drenar rápido.
En la dirección contraria, la nube usa comandos. Cuando el dueño cambia algo desde el panel web, la nube encola un comando pendiente5. El hotel consulta la nube cada 3 segundos, trae ese comando, lo aplica localmente y responde si funcionó o falló.
La regla es simple: la nube pide, pero el hotel aplica.
También hay deduplicación6. Si un comando se aplica, pero falla la confirmación, el siguiente intento no lo aplica dos veces. Solo vuelve a confirmar el resultado.
Hay un caso especial: el login. Antes de validar el PIN, el sistema intenta traer cambios recientes con un límite de espera de 2 segundos. Si la nube está lenta, no dejamos bloqueado al recepcionista.
La experiencia real
No vendemos esto como "tiempo real perfecto".
La frase correcta es: normalmente se propaga en pocos segundos, y el hotel sigue funcionando aunque la nube no esté disponible.
Para una acción remota, el camino es: el dueño cambia algo, la nube crea un comando, el hotel lo trae, lo aplica, genera un evento y ese evento vuelve a la nube.
Por eso la interfaz muestra estados como pendiente, aplicado o fallido. Es mejor decir la verdad que fingir que una acción remota ya ocurrió.
Por qué no arrancamos con conexiones vivas
WebSockets7 o SSE8 pueden bajar la latencia. No son una mala idea, pero no eliminan los problemas difíciles: colas, reintentos, deduplicación, estados pendientes y recuperación después de estar sin conexión.
Además, HotelManager corre en hoteles reales: PCs con Windows, routers comunes, conexiones imperfectas, reinicios y poca supervisión técnica.
Las consultas periódicas nos dieron una superficie operativa más simple:
- Cada intento es una solicitud HTTP9.
- Reconectar es volver a intentar.
- Los errores se pueden registrar y mostrar.
- Los reintentos tienen límite.
- Los comandos se pueden reintentar sin duplicar el cambio.
- Soporte puede entender si algo está pendiente, aplicado o fallido.
En este producto, esa claridad vale mucho. Un hotel no se cae porque el panel vea un dato 2 segundos tarde. Se cae si recepción no puede operar o si nadie entiende qué pasó cuando volvió internet.
La pregunta de escala
Las consultas periódicas mal diseñadas pueden ser caras. Por eso la cola de salida importa: el lado hotel-a-nube no manda solicitudes vacías cuando no hay eventos.
El costo fijo más importante hoy está del lado nube-a-hotel. Un hotel conectado consulta si hay comandos o snapshots de configuración10, y eso también funciona como señal de vida.
Para un piloto y una primera etapa de producción, ese costo es aceptable: es simple, observable y predecible. Si crece demasiado, podemos mejorar el transporte sin cambiar el modelo:
- Combinar chequeos de configuración y comandos.
- Agregar jitter11 para que los hoteles no consulten todos al mismo segundo.
- Alargar el intervalo cuando no hay trabajo.
- Pasar comandos a long polling12.
- Activar un canal SSE8.
La arquitectura importante no son las consultas periódicas. Es cola de salida más cola de comandos, con aplicación segura y confirmación.
El transporte puede evolucionar.
La decisión real
Elegimos 5 segundos para publicar eventos porque era rápido para la experiencia, barato para la primera escala y fácil de depurar.
Lo combinamos con comandos cada 3 segundos, drenaje rápido en 100ms cuando hay trabajo y backoff hasta 5 minutos cuando hay fallas.
Mantuvimos la operación local como fuente de verdad porque el mostrador es el centro del producto.
No consultamos cada cierto tiempo porque sí. Es una forma deliberada de comprar simplicidad sin renunciar a una experiencia de segundos.
Para quien quiera mirar más
La documentación de Stripe sobre webhooks y su guía de PaymentIntents explican por qué conviene evitar consultas periódicas contra APIs públicas cuando hay eventos asincrónicos.
El blog técnico de Dropbox sobre long polling muestra una alternativa interesante cuando el problema real pasa a ser bajar latencia o tráfico en reposo.
Notas
- Una base cifrada protege los datos para que no puedan leerse sin la clave correcta.
- 100ms es una décima de segundo. Se usa cuando ya apareció trabajo y conviene vaciar la cola rápido.
- Backoff progresivo es esperar cada vez más antes de reintentar después de una falla.
- Cola de salida es la lista local de cambios pendientes de enviar a la nube.
- Un comando pendiente es una instrucción que la nube deja preparada para que el hotel la aplique.
- Deduplicación permite reintentar sin aplicar dos veces el mismo cambio.
- WebSocket es una conexión permanente entre dos sistemas.
- SSE es un canal donde el servidor puede empujar novedades al cliente.
- HTTP es el protocolo normal de la web; acá es una llamada simple entre hotel y nube.
- Un snapshot de configuración es una foto completa de cierta configuración.
- Jitter es un pequeño retraso aleatorio para que todos los hoteles no consulten al mismo segundo.
- Long polling es una consulta que queda abierta hasta que aparezca algo nuevo o venza el tiempo.