Jobs agendados
Um Job agendado executa uma tarefa automaticamente nos horários que você definir, como gerar um relatório toda madrugada ou limpar dados antigos a cada hora. Você não precisa manter uma aplicação ligada o tempo todo: a Zenifra inicia a tarefa no horário, acompanha a execução e cobra só pelo tempo em que ela rodou.
Este guia mostra como usar Jobs pelo Console. Para automatizar pela API ou pela CLI, veja a referência da API de Jobs agendados.
Como funciona
- Horário em UTC: o horário é definido por uma Expressão cron de cinco campos e é sempre interpretado em UTC.
- No máximo uma execução por vez: se chegar o próximo horário enquanto uma execução ainda está em andamento, esse horário é pulado. Ele não é enfileirado nem executado depois.
- Limite de 60 minutos: uma execução que não termina em 60 minutos é encerrada e aparece como Tempo limite excedido.
- Sem nova tentativa automática: se uma execução falhar, a Zenifra não tenta de novo para aquele horário. A próxima execução acontece no próximo horário agendado.
- Cobrança por minuto: você paga pelo tempo em que a tarefa realmente rodou, em BRL.
Criar um Job no Console
Vídeo: criação de um Job agendado, do formulário à página com horário e execuções.
- No menu, clique em Criar projeto e escolha Job agendado.
- Escolha seu plano. Cada plano mostra os recursos (vCPU, memória e armazenamento) e o preço por minuto.
- Em Informações Básicas, dê um nome ao projeto.
- Em Configurar Job agendado, preencha:
- Origem da tarefa: escolha Imagem Docker ou Repositório GitHub.
- Com Imagem Docker, informe a Imagem da tarefa: a referência completa de uma imagem Docker pública, com registro e tag ou digest (por exemplo,
docker.io/library/alpine:3.20). O Console usa o comando padrão da própria imagem, então ela precisa executar a tarefa e terminar sozinha. - Com Repositório GitHub, escolha o repositório, a Branch, o Runtime (Node.js, Python, Bun, Go, Java ou PHP), a Versão, o Diretório raiz e o Comando da tarefa. Veja Usar um repositório do GitHub.
- Expressão cron: cinco campos, em UTC. Logo abaixo, o Console mostra os Próximos horários de execução (UTC) para você conferir.
- Armazenamento da tarefa: a capacidade em GB. Ative Manter dados entre execuções e informe o Diretório persistente (por exemplo,
/data) se a tarefa precisar guardar arquivos de uma execução para a outra.
- Em Variáveis de Ambiente, adicione as configurações que a tarefa usa, como chaves e endereços. Linhas vazias são ignoradas.
- Confira o Resumo de Custos e clique em Criar Job.



O Console não pede porta, domínio nem instâncias, porque um Job não é um site ou uma API: ele roda, termina e espera o próximo horário.
Para usar uma imagem privada ou um comando e argumentos diferentes dos padrões da imagem, crie o Job pela API.
Usar um repositório do GitHub
Com Repositório GitHub, a Zenifra faz o build do seu código e usa o resultado em todas as execuções. Se o GitHub ainda não estiver conectado à sua conta, o Console mostra como conectar antes de listar os repositórios.
- Diretório raiz: a pasta do repositório onde está a tarefa. Use
.para a raiz. - Comando da tarefa: o comando executado a cada horário agendado, por exemplo
node src/index.js. Ele precisa terminar sozinho, como na imagem Docker. A Zenifra executa esse comando diretamente, para que a tarefa receba o aviso de encerramento quando uma execução é cancelada, pausada ou excluída; em um comando encadeado com&&ou;, isso vale para a última etapa. Comandos com|ou||não recebem esse aviso, então prefira chamar um script. - Modo de deploy: define quando um novo build acontece: Manual, Automático por branch (a cada push na branch), Por Tag ou Por Release.
O primeiro build acontece na criação, e o Job começa a executar nos horários depois que ele termina. Os builds seguintes ficam em Logs de build, na página do projeto, onde também está o botão Novo build. Um build novo vale para as próximas execuções e não interrompe uma execução em andamento.
O tempo de build não é cobrado: a cobrança considera só o tempo em que a tarefa roda.
Para começar, use os exemplos de Jobs agendados em Node.js, Bun e Python, que já seguem estas recomendações.
Exemplos de horário
| Quando executar | Expressão cron |
|---|---|
| A cada 15 minutos | */15 * * * * |
| Toda hora, no minuto 0 | 0 * * * * |
| Todo dia às 03:00 (UTC) | 0 3 * * * |
| De segunda a sexta às 12:30 (UTC) | 30 12 * * 1-5 |
| Todo dia 1º do mês, às 06:00 (UTC) | 0 6 1 * * |
Lembre-se de converter o seu horário local para UTC. Por exemplo, 00:00 no horário de Brasília (UTC−3) corresponde a 03:00 UTC.
A expressão aceita valores, *, listas (,), intervalos (-), passos (/), nomes de mês e de dia da semana em inglês (jan, mon) e ? no dia do mês ou no dia da semana. O dia da semana vai de 0 (domingo) a 6; 7, L, W, # e H não são aceitos. Veja o formato completo na API de Jobs agendados.
Desligar os projetos de um time num horário
Um Job pode pausar os projetos de um time todo dia num horário, por exemplo às 20:00, e outro pode retomá-los na manhã seguinte. Assim a organização não paga pelos projetos fora do horário de uso.
- Em Chaves de API, crie uma chave com as permissões Visualizar projeto e Parar projeto (e Retomar projeto, se for religar). Quem cria a chave limita o alcance dela: a chave de um mantenedor só chega aos projetos que ele já pode operar. Veja API Keys.
- Num repositório seu no GitHub, crie o arquivo abaixo.
- Crie um Job agendado sem time, com Repositório GitHub, runtime Node.js 22 ou mais novo e Comando da tarefa
node pause-team.mjs. - Use a Expressão cron do horário em UTC. Para pausar às 20:00 de Brasília de segunda a sexta:
0 23 * * 1-5. - Em Variáveis de Ambiente, adicione
ZENIFRA_API_KEY(a chave do passo 1) eTEAM_NAME(o nome do time, exatamente como aparece em Times).
// Pausa os projetos de um time. Com ACTION=resume, retoma os que estão pausados.
const api = 'https://api.zenifra.com/v1'
const headers = { Authorization: `Bearer ${process.env.ZENIFRA_API_KEY}` }
const resume = process.env.ACTION === 'resume'
const call = async (path, method = 'GET') => {
const response = await fetch(`${api}${path}`, { method, headers })
if (!response.ok) throw new Error(`${method} ${path} respondeu ${response.status}`)
return response.json()
}
const targets = []
for (let page = 1, pages = 1; page <= pages; page += 1) {
const { data } = await call(`/project?page=${page}&limit=50`)
pages = data.pagination.pages
for (const project of data.projects) {
if (project.owner_team?.name !== process.env.TEAM_NAME) continue
if (resume ? project.status === 'stopped' : ['running', 'failing'].includes(project.status)) targets.push(project)
}
}
for (const project of targets) {
await call(`/project/${project.id}/${resume ? 'resume' : 'stop'}`, 'PATCH')
console.log(`${resume ? 'Retomado' : 'Pausado'}: ${project.name}`)
}
console.log(`${targets.length} projeto(s) do time ${process.env.TEAM_NAME}`)Para religar, crie um segundo Job com o mesmo repositório e a variável ACTION=resume, com o horário de volta (por exemplo, 0 10 * * 1-5 para 07:00 de Brasília).
A pausa é a mesma do botão Pausar do projeto: nada é apagado, e a cobrança por hora do projeto para enquanto ele está pausado. Quem tem acesso ao projeto pode retomá-lo antes do horário.
Como o resultado de uma execução é definido
O resultado depende de como o processo da sua imagem termina:
- código de saída 0 significa sucesso, e a execução aparece como Concluída;
- qualquer código de saída diferente de zero (não-zero) significa falha, e a execução aparece como Falhou; o código 1 é só o exemplo mais comum;
- se o processo não terminar em 60 minutos, a execução aparece como Tempo limite excedido.
Imagens de servidor web, que ficam esperando requisições, nunca terminam sozinhas e sempre acabam em Tempo limite excedido. Para um Job, use uma imagem cujo comando padrão execute a rotina e termine.
Acompanhar as execuções


A página do projeto concentra tudo o que acontece com o seu Job.
Horário do Job
O card Horário do Job mostra a expressão cron atual e o fuso horário (UTC). Clique em Editar para mudar o horário; a mudança vale para as próximas execuções.
Variáveis de ambiente
Clique em Editar e, em Variáveis de Ambiente, altere, adicione ou remova variáveis e clique em Salvar Variáveis de Ambiente. A mudança vale para as próximas execuções: uma execução em andamento continua com os valores anteriores, e uma variável removida deixa de existir a partir da execução seguinte.
Lista de execuções
O card Execuções lista as execuções do ciclo de cobrança atual, com:
- Agendada para: o horário programado;
- Status: a situação da execução;
- Duração: quanto tempo a tarefa rodou;
- Minutos cobrados: os minutos usados no cálculo do valor.
Clique em Atualizar execuções para ver as novidades. Os status possíveis são:
| Status | O que significa |
|---|---|
| Em execução | A tarefa está rodando agora. |
| Concluída | O processo terminou com código de saída 0. |
| Falhou | O processo terminou com um código de saída diferente de zero. |
| Tempo limite excedido | O processo não terminou dentro de 60 minutos. |
| Cancelada | A execução foi cancelada por alguém da organização ou por uma pausa/exclusão do Job. |
Logs
Clique em Ver logs em uma execução para ler o que a tarefa escreveu durante aquela execução. Os logs ajudam a entender uma falha ou confirmar o que foi processado.
Os logs continuam disponíveis depois que a execução termina, falha, excede o tempo limite ou é cancelada, inclusive o que a tarefa escreveu ao ser encerrada. A Zenifra guarda os últimos 50 KB de log de cada execução.
Métricas
Clique em Ver métricas para acompanhar o uso de CPU e memória da execução. Enquanto ela roda, o Console mostra Coletando métricas com os valores mais recentes; depois do término, mostra média e pico. Métricas indisponíveis significa que não houve amostras suficientes (por exemplo, em execuções de poucos segundos) — não significa uso zero.
As métricas por execução fazem parte do plano job-premium. Nos outros planos, o botão Ver métricas não aparece. Além do plano, a pessoa precisa da permissão Visualizar métricas.
Cancelar, pausar, retomar e excluir
Cancelar uma execução
Na lista de execuções, clique em Cancelar execução na execução em andamento e confirme. A Zenifra dá até 30 segundos para a tarefa terminar de forma graciosa e, se ela não terminar, faz a limpeza forçada.
A cobrança vai só até o momento em que você confirmou o cancelamento; os segundos de encerramento não são cobrados. Cancelar uma execução não muda o horário: a próxima execução acontece normalmente.
Pausar e retomar
Clique em Pausar e confirme em Pausar projeto para interromper os próximos horários. Se houver uma execução em andamento, ela também é cancelada, com cobrança até o momento da pausa. Para voltar a executar nos horários programados, clique em Retomar.
Excluir um Job
Clique em Excluir e confirme. Se houver uma execução em andamento, ela é cancelada e cobrada até o momento da exclusão, e então o projeto é removido. Se aparecer um aviso de que execuções ainda estão sendo finalizadas, aguarde alguns instantes e tente de novo — não é preciso repetir várias vezes.
Permissões
Cada ação do Console depende de uma permissão do papel da pessoa na organização. As permissões são configuradas na tela Membros, na seção Projetos:
| No Console | Permissão necessária |
|---|---|
| Criar um Job | Criar projeto |
| Abrir o Job, ver o horário e a lista de execuções | Visualizar projeto |
| Ver logs de uma execução | Visualizar logs |
| Ver métricas de uma execução (plano job-premium) | Visualizar métricas |
| Ver o Custo do ciclo atual | Visualizar custos |
| Editar o horário do Job | Atualizar agendamento |
| Ver as Variáveis de Ambiente do Job | Visualizar ambiente |
| Salvar Variáveis de Ambiente | Atualizar ambiente |
| Cancelar execução | Cancelar execuções do Job |
| Pausar o Job | Parar projeto |
| Retomar o Job | Retomar projeto |
| Excluir o Job | Excluir projeto |
Quando falta uma permissão, o Console esconde ou desabilita a ação correspondente e informa que o seu acesso não a inclui.
Cobrança
Preço por minuto
Jobs agendados são cobrados somente por minuto; não há cobrança por hora, mensal ou anual para esse tipo de projeto. Cada plano tem um preço por minuto, em BRL, mostrado no Console ao escolher o plano. Como os valores são frações de centavo, o Console mostra até seis casas decimais para o preço por minuto e até quatro para valores e totais — por exemplo, R$ 0,000167 por minuto.
Como os minutos são contados
- A cobrança considera o início e o fim reais da tarefa. O tempo de preparação, como o download da imagem, não é cobrado, e uma execução que nunca chegou a iniciar não gera cobrança.
- A duração é arredondada para o minuto cheio seguinte, com mínimo de 1 minuto e máximo de 60.
- O valor de cada execução é armazenado exato, sem arredondamento para cima: uma execução que custa R$ 0,0005 é cobrada como R$ 0,0005.
- Execuções que falharam, foram canceladas depois de iniciar ou excederam o tempo limite cobram o tempo efetivamente usado.
- Uma execução em andamento ainda não gera cobrança; o valor aparece quando ela termina.
| Duração da execução | Minutos cobrados |
|---|---|
| 1 segundo | 1 |
| 59 segundos | 1 |
| 70 segundos | 2 |
| 60 minutos | 60 |
Custo do ciclo atual
O card Custo do ciclo atual soma os valores armazenados das execuções concluídas no ciclo, mostrando também quantas execuções houve e quantos minutos foram contabilizados. Cada execução entra no custo depois que o valor dela é registrado, o que leva alguns instantes após o término, mesmo antes do processamento financeiro da cobrança. Esse valor não muda se o preço do plano mudar depois.
A linha Reinicia em mostra a próxima data de cobrança; quando não há uma próxima data definida, ela não aparece. Nessa data, a lista de execuções, o custo do ciclo, os logs e as métricas exibidos recomeçam do zero, independentemente da liquidação financeira. Cada execução pertence ao ciclo em que começou, mesmo que termine depois da virada.
Os registros de execução, de logs e de métricas são mantidos internamente por até 90 dias. O uso materializado e os registros financeiros ficam guardados para auditoria e não são apagados quando o ciclo exibido recomeça.
Na cobrança do ciclo, os valores são somados e descontados primeiro do saldo da organização; o que faltar é cobrado no cartão em centavos inteiros, e a fração de centavo restante fica para o próximo ciclo. Veja mais em Pagamentos e cobrança.
Armazenamento
O armazenamento efêmero é criado para cada execução e não adiciona cobrança, mas os dados não são preservados para a próxima execução. Com Manter dados entre execuções ativo, os arquivos no Diretório persistente ficam guardados, e o armazenamento persistente é cobrado à parte, por GB-hora, enquanto o projeto existir — inclusive pausado — até a exclusão.
Diagnóstico rápido
| O que você vê | O que fazer |
|---|---|
| Falhou | Abra Ver logs, procure a mensagem de erro e confirme que a imagem executa o comando esperado. |
| Tempo limite excedido | A tarefa não terminou em 60 minutos. Verifique se a imagem é de uma rotina que termina sozinha (e não de um servidor) ou divida o trabalho em partes menores. |
| Métricas indisponíveis | A execução foi curta demais para ter amostras; isso não indica uso zero. |
| Nenhuma execução nova | Confira a expressão cron em UTC nos Próximos horários de execução, se o projeto não está pausado e se não há outra execução em andamento — horários pulados não são enfileirados. |
| A exclusão pede para aguardar | Execuções ainda estão sendo finalizadas; espere alguns instantes e tente novamente. |
Próximos passos
- Referência da API de Jobs agendados — automação, imagens privadas e comandos personalizados
- Métricas e Logs
- Pagamentos e cobrança
Última atualização em