Modelo mental
Si SNS es un altavoz, SQS es un buzón. Guarda lo que le echas hasta que alguien viene a recogerlo, y el backlog no tiene techo: puedes acumular millones de mensajes sin que la cola se inmute.
Pero tiene una regla que descoloca a todo el mundo la primera vez:
Recibir un mensaje no lo borra. Lo esconde.
Cuando llamas a ReceiveMessage, SQS te entrega el mensaje y arranca un
cronómetro —el visibility timeout, 30 segundos por defecto— durante el cual
ese mensaje es invisible para los demás consumidores. Tienes ese rato para
procesarlo y llamar a DeleteMessage. Si no lo haces, el cronómetro expira, el
mensaje reaparece en la cola y otro consumidor lo coge.
Ese diseño es deliberado y es lo que hace a SQS fiable: si tu consumidor muere a mitad de proceso, nadie tiene que enterarse ni avisar a nadie. El mensaje vuelve solo. El precio es que el borrado es responsabilidad tuya y que el reloj hay que ajustarlo a mano.
El ciclo, entonces, tiene tres pasos y no dos:
ReceiveMessage— el mensaje se oculta- tu código hace el trabajo
DeleteMessage— ahora sí desaparece
Con Lambda, el event source mapping hace el 1 y el 3 por ti: borra el mensaje si tu función termina sin lanzar. Es cómodo y es también la razón por la que mucha gente lleva años usando SQS sin saber que el visibility timeout existe — hasta el día que su función tarda más de lo previsto.
La cola no empuja: alguien pregunta. Por defecto ese sondeo es short
polling, que responde al instante aunque no haya nada. Casi siempre quieres
long polling (WaitTimeSeconds hasta 20 segundos): menos respuestas vacías,
menos latencia y menos factura.
Cómo te factura
Se paga por peticiones, no por mensajes ni por almacenamiento:
| Concepto | Precio aproximado |
|---|---|
| Colas estándar | ~0,40 USD / millón de peticiones |
| Colas FIFO | algo más caro por petición |
| Primer millón de peticiones al mes | gratis |
| Guardar mensajes en la cola | sin coste |
Dos reglas mueven la factura mucho más que el precio unitario:
Cada porción de 64 KB cuenta como una petición. La documentación de precios es explícita: una acción con un payload de 1 MiB se factura como 16 peticiones. Mandar el hecho y una referencia a S3 en vez del documento entero no es solo más limpio, es dieciséis veces más barato.
El sondeo también factura, haya mensajes o no. Una cola vacía conectada a
una Lambda genera peticiones ReceiveMessage las veinticuatro horas. No arruina
a nadie, pero explica la línea de SQS cuando el sistema “no está haciendo nada”.
Long polling con 20 segundos reduce ese goteo a la vigésima parte de lo que
costaría sondeando cada segundo.
Y una que ahorra de verdad: los lotes. Diez mensajes en una llamada son una petición, no diez. Si controlas el productor, batear es la optimización más rentable que vas a hacer aquí.
Cuándo NO usarlo
- Varios consumidores tienen que ver el mismo mensaje. Una cola reparte, no duplica: cada mensaje lo recibe uno solo. Dos consumidores compartiendo cola es un reparto de carga, no un fan-out. Eso es SNS o EventBridge delante.
- Necesitas volver a leer lo que ya pasó. Un mensaje borrado no existe. No hay replay, no hay “los últimos siete días de eventos”. Eso es Kinesis.
- Necesitas orden global. FIFO ordena dentro de un grupo de mensajes, no en toda la cola — y si metes todo en un solo grupo, tu throughput se desploma a lo que dé una sola partición.
- Necesitas la respuesta para seguir. Una cola es asíncrona por definición. Montar request-reply sobre SQS se puede, pero si el cliente está esperando, casi siempre querías una llamada síncrona.
- La espera pasa de 15 minutos. El retraso máximo de un mensaje son 15 minutos. Para “recuérdame dentro de tres días”, EventBridge Scheduler o Step Functions.
Errores comunes
El visibility timeout más corto que el proceso. Es el error número uno y no falla ruidosamente: falla duplicando trabajo. Tu función tarda 45 segundos, el timeout son 30, así que a los 30 el mensaje reaparece y un segundo consumidor empieza a procesarlo mientras el primero sigue vivo. Ahora tienes dos cobros, dos emails, dos de lo que sea. Con Lambda, el visibility timeout tiene que estar cómodamente por encima del timeout de la función, no ajustado.
No activar reportBatchItemFailures. Sin eso, si un mensaje de un lote de
diez falla, los diez vuelven a la cola y los nueve buenos se reprocesan. Un solo
mensaje venenoso puede tener a tu función dando vueltas indefinidamente.
No poner DLQ. Sin redrivePolicy, un mensaje que siempre falla se reintenta
hasta agotar la retención — hasta 14 días de invocaciones que siempre fallan,
que sí se facturan.
Quedarse en short polling. Es el valor por defecto y casi nunca es lo que quieres: más respuestas vacías, más latencia percibida y más peticiones.
Asumir orden en una cola estándar. La documentación dice literalmente que los mensajes “pueden llegar desordenados”. Si tu lógica depende del orden de llegada, funcionará en desarrollo y fallará en producción bajo carga.
Olvidar que hay un techo de mensajes en vuelo. Unos 120 000 en colas estándar. No se llega procesando rápido: se llega cuando los consumidores no dan abasto y todo se queda recibido y sin borrar.
Fuentes
Cuotas de mensajes, tamaños, visibility timeout y throughput FIFO: Amazon SQS message quotas. Mensajes en vuelo, long polling y retrasos: Amazon SQS standard queue quotas. Garantías de entrega y desorden: Amazon SQS standard queues. Regla de facturación por porciones de 64 KB: SQS pricing. Los importes concretos proceden de la página de precios de AWS, que se renderiza dinámicamente y no pudo citarse literalmente: trátalos como orden de magnitud.