Serverless ou container: qual usar para bots e APIs

Use serverless para código curto disparado por evento, como um webhook ou uma API de tráfego irregular. Use container para processos que precisam ficar ligados, como bots com Gateway, WebSockets e filas.

Atualizado em 6 min de leitura

Objetivos de aprendizado

Depois de ler este artigo, você vai conseguir:

  • Entender a diferença entre função serverless e container
  • Reconhecer limites como timeout, cold start e conexão persistente
  • Escolher o modelo certo para um bot ou uma API
Nesta página

Quase todo desenvolvedor que publica um bot ou uma API esbarra na mesma dúvida: subir uma função que só roda quando alguém chama, ou um container que fica ligado o tempo todo. As duas opções funcionam, mas resolvem problemas diferentes, e escolher errado aparece como timeout, bot que cai sozinho ou conta que não fecha.

A comparação abaixo usa os critérios que pesam na prática: duração da execução, conexões persistentes, cold start, estado e custo. Os limites citados vêm da documentação da AWS (Lambda), do Google Cloud (Cloud Run) e do Discord. Esses valores mudam de tempos em tempos, então confira a página oficial de cada provedor antes de projetar em cima deles.

Serverlessambiente novo a cada chamadarequisiçãocold startambiente someContainerprocesso sempre ligadoinícioum processo contínuo atende tudotempo
Em serverless, cada chamada pode criar um ambiente, com cold start, que depois some; o container inicia uma vez e atende tudo.

O que é serverless?#

Em serverless (também chamado FaaS, "função como serviço"), você entrega uma função. O provedor cria um ambiente de execução quando chega uma requisição ou um evento, roda a função e depois congela ou descarta o ambiente. Você não escolhe máquina nem mantém sistema operacional, e o número de ambientes acompanha a demanda, inclusive até zero quando ninguém chama.

O exemplo clássico é o AWS Lambda. Um webhook do Telegram em Python cabe em uma função:

python
import json
import os
import urllib.request


def handler(event, context):
    # Recusa chamadas sem o secret_token definido no 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"}

Com uma Function URL, o corpo da requisição chega como texto em event["body"], e o cabeçalho X-Telegram-Bot-Api-Secret-Token traz o secret_token que você definiu no setWebhook. Cada mensagem vira uma invocação. Entre uma e outra não existe processo seu rodando. Compare com o long polling, em que um processo fica perguntando por novidades.

O que é um container?#

Um container é um processo isolado, empacotado com suas dependências, que roda continuamente até você parar. Para a base técnica, veja o que é Docker e containers versus máquinas virtuais. Para o desenvolvedor, a diferença decisiva é esta: o seu código inicia uma vez e mantém memória, conexões e timers abertos.

Um bot de Discord com Gateway é o caso típico:

js
import { Client, Events, GatewayIntentBits } from "discord.js";

const client = new Client({ intents: [GatewayIntentBits.Guilds] });

client.once(Events.ClientReady, (c) => console.log(`Online 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);

Esse processo precisa continuar vivo para receber eventos. Se ele sumir, o bot fica offline (veja como manter um bot 24/7).

Quais são os limites do serverless?#

Os limites variam por provedor, mas os das funções padrão do AWS Lambda ilustram o formato (variantes mais novas do Lambda têm limites próprios):

  • Duração: uma invocação roda por até 900 segundos (15 minutos).
  • Memória: de 128 MB a 10.240 MB, e a CPU cresce proporcionalmente à memória configurada.
  • Payload: 6 MB de requisição e de resposta em chamadas síncronas.
  • Disco: /tmp entre 512 MB e 10.240 MB, sem garantia de persistir.
  • Ambiente: o Lambda reaproveita ambientes por um tempo, mas os encerra a cada poucas horas, então o código não pode assumir que o estado sobrevive.

O Google Cloud Run, que roda containers sob demanda, mostra que a fronteira entre os modelos é menos nítida do que parece: o timeout de requisição padrão é de 5 minutos e pode chegar a 60 minutos. Mesmo assim, o desenho da aplicação continua tendo de aceitar que o processo pode ser criado e destruído a qualquer momento.

O que é cold start e quando ele atrapalha?#

Cold start é o custo da primeira invocação em um ambiente novo: baixar o código, iniciar o runtime e executar a inicialização fora do handler. Segundo a AWS, a duração varia de menos de 100 ms a mais de 1 segundo, e ocorre em menos de 1% das invocações. Para uma API com tráfego regular, isso é quase irrelevante. Para um endpoint chamado raramente, quase toda chamada paga esse atraso.

Isso pesa quando o prazo de resposta é curto. O Discord exige a resposta inicial a uma Interaction em até 3 segundos, e o token da interação vale 15 minutos para respostas posteriores. Um cold start somado a uma consulta lenta ao banco pode estourar esse prazo. A saída é responder com "deferred" logo no início e editar a mensagem depois.

Os provedores oferecem mitigação, como a concorrência provisionada do Lambda, que mantém ambientes prontos. Nesse ponto você volta a pagar por capacidade parada, que é o que o container já faz.

Por que bots de Gateway e WebSockets não combinam com serverless?#

O Gateway do Discord é um WebSocket persistente. A conexão exige heartbeats em intervalo regular, e se o seu app não envia um heartbeat a tempo, o Discord fecha a conexão e você precisa retomar a sessão. Uma função com limite de 15 minutos e ambiente descartável não consegue manter isso. O mesmo vale para qualquer servidor WebSocket, para workers que consomem fila continuamente e para bots de WhatsApp baseados em sessão aberta.

Há duas exceções reais. Bots do Discord podem receber comandos por HTTP (Interactions via endpoint), sem Gateway, e aí uma função basta, mas você perde eventos como mensagens e presença. E um bot de Telegram em modo webhook funciona bem em serverless, porque cada update chega como requisição.

Como comparar os dois lado a lado?#

Critério Serverless (função) Container
Unidade de deploy Função e seu handler Processo ou imagem
Tempo de execução Limitado (ex.: 15 min no Lambda) Contínuo, enquanto o processo viver
Conexão persistente Não Sim
Estado em memória Não confiável Mantido enquanto o processo vive
Cold start Existe Só no início do processo
Escala Automática por requisição, até zero Você define a RAM e o número de instâncias
Cobrança típica Por invocação e duração Por capacidade reservada
Bom para Webhooks, jobs curtos, tráfego irregular Bots, WebSockets, filas, APIs constantes
Ponto de atenção Timeouts, limites de payload, custo com volume alto Reinício, logs e dimensionamento ficam com você

Não há vencedor universal. O custo depende do padrão de tráfego: poucas chamadas favorecem pagar por invocação, carga constante favorece capacidade fixa. Faça a conta com o seu volume antes de decidir.

Qual escolher para o seu caso?#

  • Bot de Discord com Gateway, bot de música ou bot de WhatsApp com sessão aberta (Baileys, whatsapp-web.js): container.
  • Bot de Telegram: os dois servem. Webhook cabe em serverless; long polling pede um processo ligado.
  • API REST com tráfego constante: container, por custo previsível e sem cold start. Veja como hospedar uma API.
  • API ou webhook com picos raros: serverless tende a compensar.
  • Tarefa agendada curta: serverless, ou um cron job dentro de um container.
  • Tarefa longa, processamento em lote: container, por causa do limite de duração.

Um híbrido também é comum: o núcleo roda em container e uma ou duas funções tratam eventos esporádicos.

Como fazer isso na Square Cloud#

A Square Cloud usa o modelo de containers: cada aplicação roda em um container isolado, sempre ligado, sem cold start e sem modo de suspensão. O reinício automático vem ligado no deploy pelo painel e religa a aplicação quando o processo encerra com erro. Como o container não dorme e o proxy não corta conexões WebSocket longas, bots com Gateway, servidores WebSocket e workers rodam sem ajustes.

Você faz o deploy por upload de ZIP no painel, pela CLI, pelo GitHub ou pela extensão do VS Code, e escolhe entre diversos runtimes, como Node.js, Python, Go e Java; veja os disponíveis hoje em Runtimes.

A escala é vertical (você muda a RAM de cada aplicação) ou horizontal por load balancing: a partir do plano Standard, você põe o mesmo domínio personalizado em várias aplicações, servidas em round-robin. Não há autoscaling: você define a capacidade. A lista completa está nos recursos da Square Cloud.

Deploy

Envie pelo GitHub, pela CLI ou em ZIP e publique em segundos

Saiba mais

Perguntas frequentes

Serverless é mais barato que container?

Depende do padrão de uso. Com poucas requisições esparsas, pagar por invocação costuma sair mais barato. Com tráfego constante ou processo sempre ligado, um container de tamanho fixo tende a ter custo mais previsível.

Dá para rodar um bot de Discord com discord.js em serverless?

Não no modelo de Gateway, porque ele exige uma conexão WebSocket aberta o tempo todo. Só funciona se o bot usar apenas Interactions por HTTP, que o Discord envia como requisições.

O que é cold start?

É o tempo extra da primeira invocação em um ambiente novo: baixar o código, iniciar o runtime e rodar a inicialização. Invocações seguintes que reutilizam o ambiente não pagam esse custo.

Serverless não usa servidor?

Usa. O nome indica que você não provisiona nem mantém a máquina: o provedor decide onde e quando o código roda.

Próximo artigoAplicação lenta no servidor: CPU steal, overselling e gargalosAplicação lenta quase sempre tem um gargalo mensurável: CPU steal, throttling, memória, disco, rede ou o próprio código. Veja como medir cada um e corrigir.