Objetivos de aprendizaje
Después de leer este artículo podrás:
- Entender la diferencia entre una función serverless y un contenedor
- Reconocer límites como el timeout, el cold start y las conexiones persistentes
- Elegir el modelo correcto para un bot o una API
En esta página
- ¿Qué es serverless?
- ¿Qué es un contenedor?
- ¿Cuáles son los límites de serverless?
- ¿Qué es el cold start y cuándo molesta?
- ¿Por qué los bots de Gateway y los WebSockets no encajan con serverless?
- ¿Cómo se comparan los dos lado a lado?
- ¿Cuál elegir para tu caso?
- Cómo hacerlo en Square Cloud
- Preguntas frecuentes
Casi todo desarrollador que publica un bot o una API se topa con la misma duda: subir una función que solo se ejecuta cuando alguien la llama, o un contenedor que se queda encendido todo el tiempo. Las dos opciones funcionan, pero resuelven problemas distintos, y elegir mal se nota como timeouts, un bot que se cae solo o una factura que no cuadra.
La comparación de abajo usa los criterios que pesan en la práctica: duración de la ejecución, conexiones persistentes, cold start, estado y costo. Los límites citados vienen de la documentación de AWS (Lambda), Google Cloud (Cloud Run) y Discord. Esos valores cambian de vez en cuando, así que revisa la página oficial de cada proveedor antes de diseñar en torno a ellos.
¿Qué es serverless?#
En serverless (también llamado FaaS, "función como servicio"), entregas una función. El proveedor crea un entorno de ejecución cuando llega una solicitud o un evento, ejecuta la función y después congela o descarta el entorno. No eliges máquina ni mantienes un sistema operativo, y el número de entornos sigue a la demanda, incluso hasta cero cuando nadie llama.
El ejemplo clásico es AWS Lambda. Un webhook de Telegram en Python cabe en una función:
import json
import os
import urllib.request
def handler(event, context):
# Rechaza llamadas sin el secret_token definido en setWebhook
headers = event.get("headers") or {}
if headers.get("x-telegram-bot-api-secret-token") != os.environ["WEBHOOK_SECRET"]:
return {"statusCode": 401, "body": "unauthorized"}
update = json.loads(event["body"])
msg = update.get("message")
if msg and msg.get("text") == "/ping":
payload = json.dumps({"chat_id": msg["chat"]["id"], "text": "pong"}).encode()
req = urllib.request.Request(
f"https://api.telegram.org/bot{os.environ['BOT_TOKEN']}/sendMessage",
data=payload,
headers={"Content-Type": "application/json"},
)
urllib.request.urlopen(req, timeout=5)
return {"statusCode": 200, "body": "ok"}Con una Function URL, el cuerpo de la solicitud llega como texto en event["body"], y el encabezado X-Telegram-Bot-Api-Secret-Token trae el secret_token que definiste en setWebhook. Cada mensaje se convierte en una invocación. Entre una y otra no hay ningún proceso tuyo en ejecución. Compáralo con el long polling, en el que un proceso se queda preguntando si hay novedades.
¿Qué es un contenedor?#
Un contenedor es un proceso aislado, empaquetado con sus dependencias, que se ejecuta de forma continua hasta que lo detienes. Para la base técnica, mira qué es Docker y contenedores frente a máquinas virtuales. Para el desarrollador, la diferencia decisiva es esta: tu código arranca una vez y mantiene abiertos la memoria, las conexiones y los temporizadores.
Un bot de Discord con Gateway es el caso típico:
import { Client, Events, GatewayIntentBits } from "discord.js";
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.once(Events.ClientReady, (c) => console.log(`En línea como ${c.user.tag}`));
client.on(Events.InteractionCreate, async (interaction) => {
if (interaction.isChatInputCommand() && interaction.commandName === "ping") {
await interaction.reply("pong");
}
});
client.login(process.env.DISCORD_TOKEN);Ese proceso tiene que seguir vivo para recibir eventos. Si desaparece, el bot queda desconectado (mira cómo mantener un bot 24/7).
¿Cuáles son los límites de serverless?#
Los límites cambian según el proveedor, pero los de las funciones estándar de AWS Lambda muestran la forma (las variantes más nuevas de Lambda tienen límites propios):
- Duración: una invocación se ejecuta durante un máximo de 900 segundos (15 minutos).
- Memoria: de 128 MB a 10.240 MB, y la CPU crece en proporción a la memoria configurada.
- Payload: 6 MB de solicitud y de respuesta en llamadas síncronas.
- Disco:
/tmpentre 512 MB y 10.240 MB, sin garantía de que persista. - Entorno: Lambda reutiliza entornos durante un tiempo, pero los cierra cada pocas horas, así que el código no puede asumir que el estado sobrevive.
Google Cloud Run, que ejecuta contenedores bajo demanda, muestra que la frontera entre los modelos es menos clara de lo que parece: el timeout de solicitud por defecto es de 5 minutos y puede llegar a 60 minutos. Aun así, el diseño de la aplicación tiene que aceptar que el proceso puede crearse y destruirse en cualquier momento.
¿Qué es el cold start y cuándo molesta?#
El cold start es el costo de la primera invocación en un entorno nuevo: descargar el código, iniciar el runtime y ejecutar la inicialización fuera del handler. Según AWS, su duración va de menos de 100 ms a más de 1 segundo, y ocurre en menos del 1% de las invocaciones. Para una API con tráfico regular, casi no importa. Para un endpoint que se llama pocas veces, casi cada llamada paga ese retraso.
Esto pesa cuando el plazo de respuesta es corto. Discord exige la respuesta inicial a una Interaction en un máximo de 3 segundos, y el token de la interacción vale 15 minutos para respuestas posteriores. Un cold start sumado a una consulta lenta a la base de datos puede pasarse de ese plazo. La salida es responder con "deferred" al principio y editar el mensaje después.
Los proveedores ofrecen mitigaciones, como la concurrencia aprovisionada de Lambda, que mantiene entornos listos. En ese punto vuelves a pagar por capacidad parada, que es lo que el contenedor ya hace.
¿Por qué los bots de Gateway y los WebSockets no encajan con serverless?#
El Gateway de Discord es un WebSocket persistente. La conexión exige heartbeats en un intervalo regular, y si tu app no envía un heartbeat a tiempo, Discord cierra la conexión y tienes que reanudar la sesión. Una función con límite de 15 minutos y entorno desechable no puede sostener eso. Lo mismo vale para cualquier servidor WebSocket, para workers que consumen una cola de forma continua y para bots de WhatsApp basados en una sesión abierta.
Hay dos excepciones reales. Los bots de Discord pueden recibir comandos por HTTP (Interactions mediante un endpoint), sin Gateway, y ahí basta con una función, aunque pierdes eventos como mensajes y presencia. Y un bot de Telegram en modo webhook funciona bien en serverless, porque cada update llega como una solicitud.
¿Cómo se comparan los dos lado a lado?#
| Criterio | Serverless (función) | Contenedor |
|---|---|---|
| Unidad de deploy | La función y su handler | Proceso o imagen |
| Tiempo de ejecución | Limitado (ej.: 15 min en Lambda) | Continuo, mientras el proceso viva |
| Conexión persistente | No | Sí |
| Estado en memoria | No confiable | Se mantiene mientras el proceso vive |
| Cold start | Existe | Solo al iniciar el proceso |
| Escala | Automática por solicitud, hasta cero | Tú defines la RAM y el número de instancias |
| Cobro típico | Por invocación y duración | Por capacidad reservada |
| Bueno para | Webhooks, tareas cortas, tráfico irregular | Bots, WebSockets, colas, APIs constantes |
| Punto de atención | Timeouts, límites de payload, costo con mucho volumen | Reinicio, logs y dimensionamiento quedan a tu cargo |
No hay un ganador universal. El costo depende del patrón de tráfico: pocas llamadas favorecen pagar por invocación, la carga constante favorece la capacidad fija. Haz la cuenta con tu volumen antes de decidir.
¿Cuál elegir para tu caso?#
- Bot de Discord con Gateway, bot de música o bot de WhatsApp con sesión abierta (Baileys, whatsapp-web.js): contenedor.
- Bot de Telegram: los dos sirven. El webhook cabe en serverless; el long polling pide un proceso encendido.
- API REST con tráfico constante: contenedor, por costo previsible y sin cold start. Mira cómo hospedar una API.
- API o webhook con picos raros: serverless suele compensar.
- Tarea programada corta: serverless, o un cron job dentro de un contenedor.
- Tarea larga, procesamiento por lotes: contenedor, por el límite de duración.
Un modelo híbrido también es común: el núcleo corre en un contenedor y una o dos funciones atienden eventos esporádicos.
Cómo hacerlo en Square Cloud#
Square Cloud usa el modelo de contenedores: cada aplicación se ejecuta en un contenedor aislado, siempre encendido, sin cold start y sin modo de suspensión. El reinicio automático viene activado en el deploy desde el panel y vuelve a arrancar la aplicación cuando el proceso termina con un error. Como el contenedor no se suspende y el proxy no corta las conexiones WebSocket largas, los bots con Gateway, los servidores WebSocket y los workers funcionan sin cambios.
Haces el deploy subiendo un ZIP en el panel, con la CLI, desde GitHub o con la extensión de VS Code, y eliges entre diversos runtimes, como Node.js, Python, Go y Java; consulta los disponibles hoy en Runtimes.
La escala es vertical (cambias la RAM de cada aplicación) u horizontal con load balancing: desde el plan Standard, pones el mismo dominio personalizado en varias aplicaciones, servidas en round-robin. No hay autoscaling: tú defines la capacidad. La lista completa está en los recursos de Square Cloud.
Deploy
Sube desde GitHub, la CLI o un ZIP y publica en segundos
Preguntas frecuentes
¿Serverless es más barato que un contenedor?
Depende del patrón de uso. Con pocas solicitudes esporádicas, pagar por invocación suele salir más barato. Con tráfico constante o un proceso siempre encendido, un contenedor de tamaño fijo tiende a tener un costo más previsible.
¿Puedo ejecutar un bot de Discord con discord.js en serverless?
No con el modelo de Gateway, porque exige una conexión WebSocket abierta todo el tiempo. Solo funciona si el bot usa únicamente Interactions por HTTP, que Discord envía como solicitudes.
¿Qué es el cold start?
Es el tiempo extra de la primera invocación en un entorno nuevo: descargar el código, iniciar el runtime y ejecutar la inicialización. Las invocaciones siguientes que reutilizan el entorno no pagan ese costo.
¿Serverless no usa servidores?
Sí los usa. El nombre indica que tú no aprovisionas ni mantienes la máquina: el proveedor decide dónde y cuándo se ejecuta el código.
Más en Deploy
Ver los 33 artículos- Qué son las variables de entornoLas variables de entorno son pares clave-valor que el sistema operativo entrega a un proceso al iniciar. Aprende a leerlas en Node.js y Python sin exponer tokens.
- Qué es un deploy o despliegueUn deploy o despliegue lleva una versión de tu código a un servidor, la prepara y la pone en marcha. Conoce las etapas, los métodos y cómo hacer rollback.
- ¿Cuánta RAM y CPU necesita mi aplicación?Dimensiona RAM y CPU midiendo el pico real de la aplicación y sumando un margen del 30%. Mira cómo medir en Node.js, Python y Java y qué hacer cuando falte.
- Deploy automático con GitHub ActionsEl deploy automático con GitHub Actions envía tu código al servidor en cada push. Mira el workflow paso a paso, los secrets, las pruebas y los errores comunes.