Pular para o conteúdo
use-cases / byo-cron-per-tenant / hero
BYO cron / agendamentos por tenant

Deixe seus clientes trazerem o próprio agendamento cron.

Seus clientes digitam a expressão cron. Você faz POST no crontab do contêiner deles. Não há fila compartilhada para fair-share, intervalo mínimo para impor nem ticket de suporte sobre "por que meu job não rodou na pico de segunda".

use-cases / byo-cron-per-tenant / mechanism

O cliente digita na sua UI. Você faz POST no contêiner dele.

Sua página de configurações renderiza um campo. O contêiner do tenant expõe uma Cron API. O submit encaminha um POST. Sem scheduler global, sem lógica de filtro por tenant, sem cap de "máximo 100 jobs entre todos os clientes".

your-backend → tenant-container
POST /users/root/entries
// o submit do formulário repassa a expressão do cliente sem alterar
POST https://acme-cron.hoody.com/users/root/entries
Content-Type: application/json

{
  "schedule": "0 9 * * 1-5",
  "command": "/jobs/sync_crm.sh",
  "comment": "Sync Salesforce contacts",
  "enabled": true
}
tenant-container → your-backend
201 Created
HTTP/1.1 201 Created
Content-Type: application/json

{
  "id": "sch_8a3f1c",
  "schedule": "0 9 * * 1-5",
  "next_run": "2026-05-04T09:00:00Z",
  "enabled": true
}

// o agendamento agora está no crontab deste tenant e em mais nenhum lugar

O serviço Hoody Cron roda dentro de cada contêiner de tenant com entradas gerenciadas e isolamento por usuário. O agendamento mora onde o trabalho roda.

use-cases / byo-cron-per-tenant / powers

O que o BYO cron te dá que um scheduler compartilhado não consegue.

Quando o agendamento mora ao lado do trabalho, as regras do agendamento multi-tenant mudam. As restrições são locais. O raio de impacto é local. Os recursos são locais.

sem fila compartilhada

Sem imposto de fair-queueing

Não há thread pool global para brigar. O seu tenant mais exigente roda a cada minuto e nunca asfixia os silenciosos — eles não estão no mesmo crontab.

self-service

Os clientes se autoatendem, você não valida

Você para de ser o porteiro do "o */1 * * * * é permitido para o seu plano?". O contêiner deles, o cron deles, a fatura de CPU deles. Sua caixa de entrada de suporte esvazia.

preso ao contêiner

O agendamento embarca com o tenant

Faça snapshot do contêiner do tenant, e o crontab vai junto. Faça rollback, restore, fork — os agendamentos vão junto. Sem estado de scheduler externo para sincronizar.

use-cases / byo-cron-per-tenant / compare

Scheduler multi-tenant compartilhado vs cron preso ao contêiner.

A diferença aparece em três lugares: a experiência do cliente, sua carga de suporte e a área de superfície de engenharia.

eixoscheduler compartilhadoBYO cron por contêiner
O que o cliente pode escolher
mínimo de 5 minutos, só dias úteis, sem execuções concorrenteslimites por plano, regras de fair-share, adiamentos no horário de pico
Qualquer expressão cron de 5 campos que o contêiner aguente*/1 * * * * se quiserem; a CPU deles paga
Onde a validação acontece
Seu código, antes de persistir, contra um modelo global de filaregex + checagem de capacidade + checagem de plano + checagem de overlap
O daemon cron do contêiner faz o parse da expressãosó sintaxe; capacidade é de um contêiner, não da frota
Raio de impacto de falha
Um job lento de um tenant trava a fila para todo mundoincidentes de noisy-neighbor, alertas em profundidade de fila
O cron de um contêiner atrasa um tenantisolamento de nível kernel; o resto da frota nem percebe

A versão do recurso com scheduler compartilhado é um mar de ressalvas. A versão BYO é uma caixa de entrada de cinco campos.

use-cases / byo-cron-per-tenant / support

O que sai do caminho quando o cron é por tenant.

Três números que mudam no dia em que você para de operar uma fila global. Cada um mapeia para um recurso que você não precisa mais escrever ou operar.

  1. regras de validação para manter0

    Adeus intervalo mínimo por plano, max-jobs-por-tenant, knobs de fair-share. O contêiner é o limite.

  2. POST por criação de agendamento

    Cliente digita, você encaminha, o contêiner faz parse. O submit da página de configurações é uma chamada REST, não uma orquestração.

  3. campos que o cliente possui5

    minuto · hora · dia-do-mês · mês · dia-da-semana. Mais macros (@hourly, @daily). POSIX padrão, não a sua DSL.

Os números refletem o modelo BYO atrelado ao contêiner — entradas cron reais escalam com a CPU de cada contêiner e o plano do cliente.

use-cases / byo-cron-per-tenant / punchline

A expressão cron do cliente é do cliente, não sua para validar contra uma fila global.

scheduler compartilhadoBYO cron por tenant
antesif (tier !== 'enterprise' && interval < 5min) reject()imposto de validação: cada cliente pagava pelo pior cliente
depoisPOST /users/root/entries → 201 Createdo agendamento mora no contêiner deles; a CPU deles, as regras deles
Ver a Cron API
use-cases / byo-cron-per-tenant / replaces

O que isso substitui.

Os pedaços de infraestrutura que um BYO cron preso ao contêiner aposenta em silêncio.

  • schedulers multi-tenant compartilhadossem fila global para fair-share
  • Quartz com filtragem por tenantsem coluna tenant_id em cada linha de job
  • UIs custom de cron-as-configos clientes digitam, o contêiner faz parse
  • Airflow gerenciado por fornecedorsem serviço de DAG para uma expressão de 5 campos
  • Sidekiq compartilhado com throttlingsem rate limiter global entre tenants
  • BullMQ com filas por tenantsem Redis para babá por cliente
use-cases / byo-cron-per-tenant / cta

Pare de ser o porteiro do agendamento dos outros. Entregue o campo cron, entregue o trabalho ao contêiner deles.

Ler a documentação
use-cases / byo-cron-per-tenant / related

Leia os outros