
Função serverless com agendamento: código sob demanda com um endpoint
Função serverless é código que roda quando alguém chama um endereço ou quando um agendamento dispara. O Functions publica o código, cria um endpoint HTTP e agenda execuções, sem servidor para manter.
Nesta página · 9 seções
Uma função serverless é um trecho de código que roda quando alguém chama um endereço ou quando um relógio manda, sem que você mantenha um servidor ligado o tempo todo. Você escreve a lógica, publica, e a plataforma executa a cada chamada ou a cada horário marcado.
Como uma função é publicada
No Functions, uma função é um módulo JavaScript com um export default. Ela recebe a requisição e um contexto com a query, o corpo e as variáveis da função:
export default (req, ctx) => {
return Response.json({ metodo: req.method, query: ctx.query })
}
O código vai como texto dentro de uma chamada POST /functions. Não há upload de arquivo, zip nem etapa de build. Publicar um nome novo cria a função e a versão 1; publicar de novo o mesmo nome cria a versão 2 e a torna ativa. O endereço /fn/<nome> não muda, e um rollback volta a versão anterior sem reenviar código.
Quem dá o nome é você, e a unicidade é do par dono e nome: dois clientes podem ter uma função chamada hello cada um, sem colidir.
Dois jeitos de disparar: por chamada ou por horário
A mesma função responde a duas origens.
Por chamada HTTP. Qualquer cliente que tenha a URL invoca /fn/<nome>. Serve para webhooks que chegam de fora, para uma página que precisa de um cálculo do servidor ou para um botão que dispara um processo. O endereço é público: quem tem a URL pode chamar, então segredo de verdade se confere dentro da função, lendo de ctx.env.
Por agendamento. Você cria um cron para a função:
curl -X POST https://functions.manager.myinfrastructure.click/schedules \
-H "x-api-key: fk_…" \
-d '{"function":"hello","cron":"0 3 * * *"}'
A expressão tem cinco campos: minuto, hora, dia, mês e dia da semana. Ela é sempre em UTC, e não existe campo de segundos. O relógio bate a cada minuto e dispara cada agendamento uma vez por horário; um agendamento novo ou editado começa a valer no minuto seguinte.
O intervalo mínimo é de 5 minutos. Uma expressão como * * * * * é recusada com um erro que informa o mínimo, e 0,2 * * * * também não passa.
| Você quer | Expressão | Observação |
|---|---|---|
| Todo dia às 3h UTC | 0 3 * * * | 3h UTC equivale a meia-noite em Brasília (UTC-3) |
| A cada 15 minutos | */15 * * * * | dentro do mínimo de 5 |
| Toda segunda às 9h UTC | 0 9 * * 1 | dia da semana: 0 é domingo |
| A cada minuto | * * * * * | recusado |
O que a função pode fazer
Ela foi feita para o trabalho que acontece dentro da requisição: transformar um payload, validar uma entrada, calcular, assinar uma mensagem, responder. Com a internet liberada, entram também chamar uma API pública ou avisar um terceiro por webhook.
Os limites reais, que você deve ter em mente antes de desenhar a função:
| Limite | Valor |
|---|---|
| Tempo por invocação | 10 segundos, de relógio e de CPU |
| Memória | 128 MB |
| Tamanho do código | 512 KB |
| Requisições de saída por invocação | 100 |
| Resposta | 1 MB |
| Intervalo entre execuções agendadas | 5 minutos no mínimo |
Estourar o tempo devolve 504. Passar de 1 MB de resposta devolve 507. Trabalho que demora mais de 10 segundos não cabe numa invocação: divida em partes ou guarde o progresso fora da função.
O que a função não pode fazer
Não tem internet por padrão. Toda função nasce com a rede desligada. Para que ela chame uma API externa, é preciso ligar a rede dessa função, com um PUT em /functions/<nome>/network. Liberar é uma decisão tomada por função, e não muda o código publicado.
Mesmo com a rede ligada, a função alcança só a internet pública, por http e https. Endereços internos ficam bloqueados: redes privadas, localhost, o endereço de metadados de nuvem e os sufixos .internal, .local e .localhost. Se o seu banco fica numa rede privada, a função não chega até ele.
Não guarda estado. Não há disco. O isolate que executa a função pode ser reaproveitado entre chamadas, então uma variável global às vezes sobrevive, mas não há garantia, e ela some quando o isolate é reciclado ou quando você publica outra versão. Estado que importa vai para fora da função.
Não instala dependências. Não há npm install nem etapa de build. A função roda com o que está no próprio arquivo, e a rede ligada serve para executar, não para instalar pacotes.
Não escreve headers de cookie ou de CORS. A resposta sai sem Set-Cookie e sem Access-Control-*, porque esses headers atravessariam o domínio compartilhado da plataforma. A função também não recebe authorization, x-api-key nem cookie: o token que a função precisa vai no corpo da requisição.
Não acessa o serviço. Cada função roda num isolate V8 próprio, sem bindings, sem segredos do serviço e sem process.env. Só recebe a requisição e as variáveis que você mesmo cadastrou para ela.
Quando não é a ferramenta certa
Se o trabalho precisa de processo longo, de WebSocket, de streaming ou de um banco numa rede privada, uma função com teto de 10 segundos não resolve. O mesmo vale para quem precisa de Python ou de uma imagem própria: aqui o runtime é JavaScript.
Para o resto, o caminho costuma ser curto: publicar, testar a chamada no endereço /fn/<nome>, agendar se houver horário, e ligar a rede só quando a função realmente precisar sair.
Perguntas frequentes
Posso rodar uma função a cada minuto?
Não. O intervalo mínimo entre execuções agendadas é de 5 minutos, e a expressão * * * * * é recusada. Se você precisa de algo mais frequente, a função de chamada HTTP funciona, desde que quem chama a dispare.
A função guarda o que aconteceu na execução anterior?
Não de forma confiável. Uma variável global pode sobreviver entre duas chamadas da mesma versão, mas o isolate pode ser reciclado a qualquer momento. Guarde o que importa num banco ou num serviço de armazenamento e leia de lá na próxima execução.
Como faço a função chamar uma API externa?
Ligue a rede da função com PUT /functions/<nome>/network e {"enabled": true}. Depois disso, fetch para endereços públicos funciona. Endereços de rede privada continuam bloqueados, mesmo com a rede ligada.
Um navegador consegue chamar a função direto da página?
Hoje, a resposta só é lida pelo navegador quando a página está num subdomínio de myinfrastructure.click, o que inclui o endereço padrão de um site do Hoster. De um domínio próprio, o navegador não consegue ler a resposta, e a pré-verificação de um POST JSON é negada e a chamada nem sai. De servidor para servidor, a chamada funciona de qualquer origem.
Para continuar lendo
Login sem senha com código no e-mail: como funciona e quando usar
Guardar dados e arquivos do app sem migration nem credencial de nuvem
Executar código sem gerenciar servidor
Quando o trabalho cabe numa requisição ou num horário marcado, o Functions entrega o endereço, o cron e a sandbox. A função nasce sem acesso à internet, roda em até 10 segundos e não garante estado entre execuções. Esses limites estão documentados para você planejar em cima deles.
Fontes
Quem escreveu
Continue lendo
Guardar dados e arquivos do app sem migration nem credencial de nuvemMais recente · · 5 min
Como cobrar assinatura no seu app sem escrever webhookMais recente · · 4 min
E-mail transacional pelo seu domínio: verificação, eventos e supressãoMais recente · · 6 min
Onde hospedar uma SPA em React ou Vite sem quebrar as rotasMais recente · · 5 min
Liberar e bloquear partes do app pelo plano do usuárioMais recente · · 4 min
Como um agente de IA faz login no seu app: OAuth 2.1 e o passo humanoMais recente · · 5 min