REST API, WebSockets y Server-Sent Events: cómo se comunican las aplicaciones web (y cuándo usar cada uno)
Ya sea que estás empezando en código o estás usando algún agente de IA para generar tu aplicación, entender cómo se comunican las aplicaciones web con el servidor te va a servir para dos cosas: ganar rendimiento y elegir el método correcto para que ciertas funcionalidades no fallen en producción.
En este artículo vamos a ver tres arquitecturas de comunicación cliente-servidor que te vas a encontrar constantemente: REST API, WebSockets y Server-Sent Events (SSE). La regla rápida sería algo así:
- ¿Vas a crear un chat? → WebSockets
- ¿Vas a mostrar notificaciones? → Server-Sent Events
- ¿Operaciones típicas (crear, listar, actualizar, eliminar)? → REST API
Pero para saber por qué, primero hay que entender la base.
La arquitectura cliente-servidor
No importa qué sitio estés usando —YouTube, Facebook, LinkedIn o cualquier web de internet—, lo primero que pasa cuando entras es esto:
- El navegador solicita una página a través de una dirección (por ejemplo
www.algo.com). Esta solicitud tiene un nombre específico: petición o request. - El servidor recibe la petición y la procesa. Dependiendo de lo que hayas solicitado, puede buscar algo en una base de datos, un archivo, una imagen... básicamente intenta resolver lo que pediste.
- El servidor retorna el resultado. A eso se le conoce como respuesta o response.
Esto es lo que hacen todas las webs y se conoce como arquitectura cliente-servidor: hay un servidor y pueden existir múltiples clientes, pero todos consumen desde ese mismo servidor. Así funciona prácticamente el 90% del internet de estos días.
Dos detalles importantes de este flujo:
- La comunicación viaja sobre un protocolo: HTTP. Es el que permite que un cliente pida algo y el servidor responda, ya sean páginas completas o simplemente datos.
- La comunicación siempre la inicia el cliente. El navegador pide, el servidor escucha y responde. Este punto es clave para entender todo lo que viene después.
REST API: la forma más común
Una REST API, en la práctica, es una aplicación de servidor: un programa que recibe las peticiones del cliente y les responde. Antes desarrollar una tomaba bastante trabajo; hoy con agentes de IA puedes crear una en cuestión de minutos. Pero más importante que crearla es entender cómo funciona.
Para probarlo, generé con un agente una aplicación de ejemplo: un tablero kanban de tareas (esas columnas donde mueves tarjetas de un lado a otro, tipo Trello o Notion), con frontend en React + Vite, backend en Express y SQLite como base de datos. Ni siquiera hace falta pedirle explícitamente que use HTTP o que cree una REST API: con decirle "frontend y backend", el agente entiende que necesita comunicarlos de algún modo, y esta es la forma por defecto.
Si le añadimos logs al backend para ver las peticiones que van llegando, el patrón aparece de inmediato:
- Muevo una tarjeta → se lanza un
PATCH(actualización de un dato) - Elimino una tarea → se lanza un
DELETE - Creo una tarea → se lanza un
POST - Recargo la página → se lanza un
GETpara solicitar los datos iniciales
Eso es una REST API funcionando: el backend va respondiendo, actualizando, eliminando y creando según lo que el cliente pida.
El problema: nadie más se entera
Aquí viene el detalle. Cuando yo cambio un dato, solo interactúan mi cliente y el servidor. Si otra persona está trabajando en el mismo tablero desde su propia interfaz y crea una "tarea 10", ella verá la respuesta del servidor en su pantalla... pero los demás no se enteran hasta que refresquen la página.
A la capacidad de que todos los clientes vean los cambios sin refrescar se le llama tiempo real (real time). Y para lograrlo existen varias estrategias.
Long polling: la forma antigua (que aún funciona)
Una técnica clásica es que el cliente consulte continuamente al servidor por si algo cambió. Gmail es el ejemplo típico: cuando surgió, la estrategia era que la aplicación del usuario preguntara cada cierto tiempo "¿tengo correos nuevos?", una y otra vez, cada ciertos segundos, sin parar.
Esto se llama long polling y funciona, pero tiene problemas evidentes:
- Puede que nunca llegue nada nuevo y aun así el cliente sigue consultando, saturando el servidor de peticiones y desperdiciando conexiones sin propósito.
- Si el cambio ocurre dentro del intervalo de espera, la interfaz no lo refleja hasta la siguiente consulta. Para el usuario parece un bug.
Lo implementé en el tablero kanban pidiéndole al agente: "Implementa long polling en el frontend para estar al tanto de actualizaciones de datos". El resultado: el navegador pedía automáticamente a la API cada ~25 segundos si había cambios. Los cambios de un cliente sí terminaban apareciendo en el otro, pero con ese retraso y ese costo de peticiones constantes.
Para una aplicación de una sola persona no notas la diferencia. El problema aparece cuando trabajan múltiples personas al mismo tiempo. Y para eso, los navegadores y servidores modernos ya tienen algo mejor.
WebSockets: comunicación bidireccional
Los WebSockets rompen la regla de que el cliente siempre inicia. Aquí el cliente se conecta al servidor, el servidor se conecta con el cliente, y a partir de allí mantienen una comunicación bidireccional: el cliente puede pedir y el servidor responder, pero también el servidor puede notificar al cliente sin que este haya pedido nada.
Volviendo al ejemplo de Gmail: si un cliente envía un correo al servidor, los demás clientes —al mantener una conexión WebSocket— ven reflejado el correo nuevo en su interfaz inmediatamente. No necesitan preguntar constantemente; el servidor les avisa.
En el tablero kanban bastó con pedirle al agente: "Cambia el long polling por WebSockets". El agente creó una ruta sobre el protocolo ws:// (el protocolo de WebSockets) y la sincronización pasó a ser instantánea: no importa cuántos clientes estén conectados, cualquiera que haga una modificación la ve reflejada en todas las demás ventanas al momento.
Para probarlo de verdad, usé un skill de Playwright CLI para lanzar cuatro instancias de navegador simultáneas: dos creando tareas y dos moviendo tarjetas entre columnas. Cada acción en una ventana se reflejaba de inmediato en las otras tres. Eso es el WebSocket haciendo su trabajo.
Server-Sent Events (SSE): cuando solo necesitas que el servidor te avise
Ahora, hay casos donde la comunicación bidireccional sobra. Piensa en una interfaz sencilla de notificaciones: alguien te asignó una tarea y solo necesitas enterarte. No tienes que responder nada al servidor ni reenviar nada para que notifique al resto.
Para eso existen los Server-Sent Events (SSE): un canal donde el servidor "empuja" (push) mensajes al cliente, y el cliente solo los recibe. Es como la mitad de un WebSocket: el WebSocket puede enviar de vuelta, pero aquí no hace falta.
Casos típicos de uso:
- Feeds en vivo: una red social donde las publicaciones nuevas aparecen solas en la interfaz de los usuarios.
- Respuestas de IA en streaming: el cliente nunca solicita cada fragmento; simplemente le van llegando los mensajes del servidor.
- Notificaciones: un error del lado del servidor, un mensaje nuevo, etc.
De hecho, los SSE resuelven la mayoría de operaciones comunes sin necesidad de comunicación bidireccional. Si lo piensas, lo que casi siempre se necesita es enviar eventos desde el servidor. Así que SSE + REST API cubre prácticamente toda la comunicación bidireccional que puedas necesitar, y por eso es incluso más común que los WebSockets.
En la demo lo combiné con todo lo anterior: "Crea un feed de actividad en vivo por Server-Sent Events (solo de servidor a cliente) mientras el WebSocket sigue sincronizando el tablero". El resultado: una tarjeta de actividad que registra en tiempo real cada cambio del tablero —quién creó, movió o eliminó qué— sin que el cliente tenga que hacer nada de vuelta.
Lo importante: no son excluyentes
Si revisas los archivos del servidor de la demo, verás las tres arquitecturas conviviendo en el mismo backend:
- Un WebSocket server (dentro de nuestro propio servidor, como una conexión) para el reordenamiento de tarjetas en tiempo real.
- Las rutas de API de siempre: la REST API para crear, consultar y modificar datos.
- Un módulo de actividad con SSE que escucha eventos y los envía al frontend, sin mantener comunicación bidireccional.
No porque uses REST API tienes que renunciar a WebSockets, ni porque uses WebSockets dejas de poder usar SSE. Todo puede funcionar dentro del mismo servidor; cada uno sirve para características distintas.
Bonus: GraphQL, otra forma de responder
Con las tres anteriores cubres la gran mayoría de proyectos. Pero a modo de información, existe otra forma de organizar la comunicación cuyo objetivo no es el tiempo real, sino la forma en la que el servidor responde: GraphQL.
El contexto es este: cuando un servidor responde, lo hace en un formato llamado JSON, una forma de organizar datos en pares clave-valor:
{
"name": "John",
"age": 30
}
En la práctica, los objetos reales traen muchos más campos. Y si envías toda esa información a un dispositivo móvil que solo necesita dos o tres datos, estás desperdiciando ancho de banda y haciéndole procesar información que no va a usar.
Ahí entra GraphQL: permite que el cliente pida exactamente los datos que necesita y nada más. En la demo lo implementé como una API adicional a la REST API, y desde su interfaz de consultas puedes pedir, por ejemplo, solo los id y title de las tareas —con autocompletado incluido— y recibir únicamente eso.
Por debajo GraphQL también usa HTTP y permite las mismas operaciones (crear, listar, incluso conexiones en tiempo real), pero está pensado más como el siguiente paso una vez que ya dominas una REST API típica.
Conclusión
Implementar comunicación en tiempo real hoy es bastante sencillo, sobre todo con agentes de IA. Y estas tres formas son las que más vas a usar, tanto si estás empezando en desarrollo como si haces vibe coding:
| Necesitas... | Usa... |
|---|---|
| Crear, listar, actualizar, eliminar datos | REST API |
| Chat o sincronización bidireccional en tiempo real | WebSockets |
| Notificaciones, feeds, streaming del servidor al cliente | Server-Sent Events |
Si conoces estas tres, puedes desarrollar casi cualquier aplicación y saber exactamente qué pedirle a tu agente según la funcionalidad que necesites. Y cuando las domines —y tu proyecto crezca— ya puedes explorar alternativas como GraphQL, gRPC o webhooks.