En el artículo anterior exploramos las dos formas principales de mantener datos frescos en una aplicación: polling y subscriptions. Entendimos cómo funcionan, cuándo usar cada una, y las diferencias entre ambas. Ahora es momento de pasar de la teoría a la práctica.
En este artículo vamos a implementar subscriptions en nuestra API de GraphQL con AWS AppSync (el servicio administrado de GraphQL que hemos usado en la serie). Vamos a construir algo concreto: suscribirnos a una publicación y recibir una notificación en tiempo real cada vez que alguien deje un nuevo comentario.
Al final de este artículo, tendrás:
- Una subscription funcionando que reacciona a nuevos comentarios
- Entendimiento de cómo AppSync implementa subscriptions (spoiler: es más simple de lo que piensas)
- La experiencia de ver datos aparecer en tiempo real en dos pestañas del navegador
Este diagrama te muestra el panorama completo de lo que construiremos:
Antes de empezar
Para seguir este tutorial necesitas:
- Tu API de AppSync con los resolvers que construimos en uno de los artículos anteriores
- Una cuenta de AWS (el free tier es suficiente)
- Un navegador web
Parte 1: ¿Cómo implementa AppSync las Subscriptions?
En el artículo anterior vimos que hay diferentes formas de implementar subscriptions (WebSockets, SSE, Long Polling). AppSync usa WebSockets por debajo, pero tiene una particularidad importante: las subscriptions se activan a través de mutations.
¿Qué significa esto? Que cuando defines una subscription en AppSync, le dices: "cada vez que se ejecute esta mutation, notifica a todos los que estén suscritos". No necesitas escribir código para enviar notificaciones, AppSync lo hace automáticamente.
El flujo se ve así:
- Un cliente se suscribe a
onNuevoComentario(publicacionId: "1") - AppSync abre un WebSocket y registra la subscription
- Otro cliente ejecuta la mutation
crearComentariopara la publicación "1" - AppSync detecta que hay una subscription vinculada a esa mutation
- AppSync envía los datos del nuevo comentario al cliente suscrito automáticamente
¿Por qué mutations? Porque las mutations son las operaciones que cambian datos en tu sistema. Si algo cambió, probablemente alguien quiere saberlo. AppSync aprovecha esto para vincular subscriptions directamente a los cambios.
Parte 2: Preparando el resolver de comentarios
Antes de implementar la subscription, necesitamos que la mutation crearComentario funcione. Si completaste el reto del artículo 4, ya la tienes lista y puedes saltar a la Parte 3.
Si no, no te preocupes, vamos a configurarla rápidamente. El proceso es el mismo patrón que aprendiste para usuario y crearUsuario:
- Crear función Lambda
- Crear data source en AppSync
- Adjuntar resolver con mapping templates
Código del resolver
Crea una nueva función Lambda con este código:
export const handler = async (event) => {
const { contenido, publicacionId, autorId } = event.arguments.input;
const nuevoComentario = {
id: Date.now().toString(),
contenido,
publicacionId,
autorId,
creadoEn: new Date().toISOString()
};
console.log("Comentario creado:", nuevoComentario);
return nuevoComentario;
};
💡 Tip importante: Usamos
Date.now().toString()para generar IDs porque es simple y funciona bien para este tutorial. En una aplicación en producción con múltiples usuarios simultáneos, querrás usar algo más robusto como UUID o dejar que tu base de datos genere los IDs automáticamente.
Mapping templates
Los mismos que usamos para los resolvers anteriores:
Request mapping template:
{
"version": "2018-05-29",
"operation": "Invoke",
"payload": {
"arguments": $util.toJson($context.arguments)
}
}
Response mapping template:
$util.toJson($context.result)
Conecta esta Lambda a AppSync como data source y adjunta el resolver a crearComentario en el esquema. Reutiliza el rol AppSyncLambdaRole que creaste en el artículo 4.
Prueba que funcione con esta mutation en el playground:
mutation CrearComentario {
crearComentario(input: {
contenido: "¡Excelente publicación!"
publicacionId: "1"
autorId: "2"
}) {
id
contenido
publicacionId
creadoEn
}
}
Si recibes los datos del comentario de vuelta, estás listo para la siguiente parte.
Parte 3: Implementando la Subscription
Ahora sí, lo que vinimos a hacer. Vamos a agregar una subscription a nuestro esquema para que cualquier cliente pueda suscribirse a los comentarios nuevos de una publicación.
Paso 1: Actualizar el esquema
Agrega este tipo al final de tu esquema en AppSync:
type Subscription {
onNuevoComentario(publicacionId: ID!): Comentario
@aws_subscribe(mutations: ["crearComentario"])
}
También necesitas agregar el campo publicacionId al tipo Comentario para que AppSync pueda filtrar las notificaciones por publicación:
type Comentario {
id: ID!
contenido: String!
autor: Usuario!
publicacion: Publicacion!
publicacionId: ID
creadoEn: String!
}
Aquí está el esquema completo actualizado para que lo copies:
type Usuario {
id: ID!
nombre: String!
email: String!
fotoPerfil: String
publicaciones: [Publicacion!]!
creadoEn: String!
}
type Publicacion {
id: ID!
contenido: String!
autor: Usuario!
comentarios: [Comentario!]!
creadoEn: String!
}
type Comentario {
id: ID!
contenido: String!
autor: Usuario!
publicacion: Publicacion!
publicacionId: ID
creadoEn: String!
}
input CrearUsuarioInput {
nombre: String!
email: String!
fotoPerfil: String
}
input CrearPublicacionInput {
contenido: String!
autorId: ID!
}
input CrearComentarioInput {
contenido: String!
publicacionId: ID!
autorId: ID!
}
type Query {
usuario(id: ID!): Usuario
publicacion(id: ID!): Publicacion
publicaciones: [Publicacion!]!
}
type Mutation {
crearUsuario(input: CrearUsuarioInput!): Usuario!
crearPublicacion(input: CrearPublicacionInput!): Publicacion!
crearComentario(input: CrearComentarioInput!): Comentario!
}
type Subscription {
onNuevoComentario(publicacionId: ID!): Comentario
@aws_subscribe(mutations: ["crearComentario"])
}
En este video puedes ver cómo agregar el tipo Subscription directamente en el editor de esquema de AppSync:
Veamos qué hace cada parte:
-
type Subscription: Define las subscriptions disponibles en tu API, igual quetype Querydefine las consultas ytype Mutationdefine las escrituras -
onNuevoComentario(publicacionId: ID!): El nombre de la subscription. Recibe el ID de la publicación a la que quieres suscribirte -
: Comentario: El tipo de dato que recibirás cuando se active la subscription -
@aws_subscribe(mutations: ["crearComentario"]): Esta es la parte clave. Le dice a AppSync: "activa esta subscription cada vez que se ejecute la mutationcrearComentario"
💡 Tip importante: La directiva
@aws_subscribees específica de AppSync. Es lo que conecta una subscription con una o más mutations. Puedes vincular una subscription a múltiples mutations si lo necesitas:@aws_subscribe(mutations: ["crearComentario", "editarComentario"]).
Paso 2: Crear un Data Source de tipo NONE
Las subscriptions no llaman a Lambda ni a ninguna base de datos, solo reenvían datos. Pero AppSync necesita un data source asociado. Para esto usamos un data source de tipo NONE, que le dice a AppSync "no llames a nadie, solo pasa los datos".
En la consola de AppSync, ve a Data Sources y crea uno nuevo:
-
Nombre:
NoneDataSource -
Tipo:
None
Paso 3: Adjuntar el resolver a la subscription
Ahora adjunta un resolver al campo onNuevoComentario en el tipo Subscription:
-
Data source:
NoneDataSource(el que acabas de crear) - Runtime: VTL
Request mapping template:
{
"version": "2018-05-29",
"payload": {}
}
Response mapping template:
null
💡 Tip importante: Fíjate que el request template usa
payload: {}y el response retornanull. Esto es porque al suscribirte no hay datos que devolver todavía, solo estás registrando tu interés. Los datos reales llegarán cuando alguien ejecute la mutationcrearComentario.
¿Por qué no necesita Lambda? Porque la subscription no "busca" datos, solo escucha. Los datos vienen de la mutation (crearComentario), que ya tiene su propio resolver. La subscription simplemente reenvía esos datos a los clientes suscritos.
Parte 4: Probando en tiempo real
Este es el momento más satisfactorio. Vamos a abrir dos pestañas del navegador y ver la magia del tiempo real.
Pestaña A: El suscriptor
En la primera pestaña del playground de AppSync, ejecuta esta subscription:
subscription EscucharComentarios {
onNuevoComentario(publicacionId: "1") {
id
contenido
publicacionId
creadoEn
}
}
Cuando la ejecutes, verás que el playground se queda "escuchando". No hay respuesta todavía, está esperando que alguien cree un comentario en la publicación "1".
💡 Tip importante: Los campos que pides en la subscription deben ser un subconjunto de los campos que pides en la mutation. Si la subscription pide un campo que la mutation no incluyó, recibirás
nullen ese campo (o un error si el campo es obligatorio en el esquema).
Pestaña B: El que comenta
Abre una segunda pestaña del playground de AppSync y ejecuta esta mutation:
mutation CrearComentario {
crearComentario(input: {
contenido: "¡Este artículo me ayudó mucho!"
publicacionId: "1"
autorId: "2"
}) {
id
contenido
publicacionId
creadoEn
}
}
💡 Tip importante: Fíjate que la mutation pide
publicacionIden los campos de respuesta. Esto es clave: AppSync usa los campos de la respuesta de la mutation para enviar datos a los suscriptores. Si no incluyespublicacionId, AppSync envíanullen ese campo. Como tu subscription filtró porpublicacionId: "1", no hay match connully no recibes la notificación.
Este diagrama muestra cómo AppSync decide a quién notificar:
El momento "aha" 🎉
Vuelve a la Pestaña A. Sin haber tocado nada, los datos del nuevo comentario aparecieron automáticamente. El servidor le avisó a tu suscriptor en el instante que la mutation se ejecutó.
En este video puedes ver la experiencia completa, suscribirse en una pestaña, crear un comentario en otra, y ver los datos aparecer en tiempo real:
Prueba crear más comentarios desde la Pestaña B, cada uno aparecerá en la Pestaña A en tiempo real.
💡 Tip importante: Fíjate que si creas un comentario con
publicacionId: "2", la Pestaña A no recibe nada. Esto es porque se suscribió específicamente a la publicación "1". El filtro porpublicacionIdfunciona automáticamente gracias a que lo definimos como argumento en la subscription.
Parte 5: Reto práctico
Ya implementaste tu primera subscription. Ahora es tu turno de expandir lo que aprendiste.
Tu reto: Implementa estas subscriptions adicionales:
onNuevaPublicacion: Suscríbete para recibir notificaciones cuando alguien cree una nueva publicación. Vincula esta subscription a la mutationcrearPublicacion.onNuevoUsuario: Suscríbete para saber cuando se registra un nuevo usuario. Vincula acrearUsuario.
Tips:
- El patrón es el mismo: agrega el tipo en
Subscription, usa@aws_subscribe, crea un resolver con elNoneDataSource, y prueba con dos pestañas - No necesitas crear nuevos resolvers de Lambda, las subscriptions usan las mutations existentes
- Puedes reutilizar el mismo
NoneDataSourcepara todas tus subscriptions - Experimenta con los campos que pides en la subscription, puedes pedir solo los que te interesen
Preguntas frecuentes
¿Las subscriptions de AppSync funcionan fuera del playground?
Sí. El playground es solo para probar. En una aplicación real, usarías librerías como AWS Amplify que manejan la conexión WebSocket automáticamente desde tu frontend (React, Vue, Angular, etc.).
¿Qué pasa si se pierde la conexión?
AppSync mantiene la conexión enviando mensajes de keep-alive periódicamente. Si la conexión se interrumpe, es responsabilidad del cliente reconectarse y volver a registrar sus subscriptions. En producción, librerías como AWS Amplify manejan esta lógica de reconexión automáticamente por ti.
¿Puedo filtrar qué datos recibo en una subscription?
Sí. Como vimos con publicacionId, los argumentos de la subscription actúan como filtros. Solo recibes notificaciones que coincidan con los argumentos que especificaste.
Conclusión
Recapitulemos lo que lograste:
- ✅ Descubriste cómo AppSync vincula subscriptions a mutations con
@aws_subscribe - ✅ Aprendiste a configurar un data source NONE y un resolver para subscriptions
- ✅ Implementaste una subscription real que reacciona a nuevos comentarios
- ✅ Viste datos aparecer en tiempo real entre dos pestañas del navegador
Hasta ahora en la serie hemos construido una API de GraphQL completa: desde entender qué es GraphQL, diseñar un esquema, desplegarlo en AppSync, implementar resolvers, y ahora agregar tiempo real con subscriptions. Pero todo lo hemos probado desde el playground de AppSync.
En el próximo artículo vamos a dar el siguiente paso: consumir nuestra API desde una aplicación cliente real. Vamos a ver cómo conectar un frontend a nuestra API y usar queries, mutations y subscriptions desde código.
¡Nos vemos ahí! 🚀




Top comments (0)