
Share the clock, keep each application's work separate
Applications declare recurring work without giving every running copy its own independent timer. A shared platform scheduler holds the schedules and dispatches each tick to the intended application’s queue.
The receiving runtime verifies the signed instruction and performs the work. Scheduling, delivery and business completion remain separate stages that an operator can inspect.
Example — Schedule two products without mixing their jobs
A customer portal creates a daily export while an operations tool refreshes external records. Both use the platform’s clock, but each dispatch names its own application and reaches its own configured queue and runtime.
For engineers
Wonder Todos declares a cron-mode minion in minions/marketing-scrapper/wildo.minion.config.ts. This selected configuration omits display metadata and comments:
import { defineMinionConfig } from '@wildo-ai/platform-config-lib';
export default defineMinionConfig({
version: 1,
name: 'marketing-scrapper',
runtime: { type: 'docker', language: 'typescript' },
mode: 'cron',
schedule: '0 */6 * * *',
reinstantiation: {
policy: 'kill_previous',
},
resources: { cpu: '500m', memory: '512Mi' },
});
The minion must also be declared in wildo.saas.config.ts, with its path and resource/platform access. Its work implementation belongs to that runtime. Synchronization brings the declaration into managed configuration; startup schedule synchronization registers the application’s jobs with the scheduler.
mode and schedule select recurring delivery. reinstantiation.policy controls replacement during deployment: the Kubernetes generator maps kill_previous to Recreate and let_run to RollingUpdate. It does not make successive cron handlers mutually exclusive. If overlapping ticks could duplicate an export or an external API charge, the application handler must coordinate that work and make its effects idempotent.
Follow the application identity through dispatch
The authenticated jobs-sync endpoint derives applicationId and the advertised broker virtual host from the application’s identity, not a target application supplied in the request body. A full sync creates or updates jobs and removes jobs no longer declared by that application.
The automatic resource-cron, custom-batch and minion extractors register their expressions in UTC, including the minion shown above. These declarations do not supply a timezone field. The lower-level application jobs-sync API accepts an explicit timezone, which the scheduler preserves; its stored-job default is UTC. Do not read that lower-level support as local-time or daylight-saving behavior for the illustrated declaration.
The scheduler validates expressions and refreshes its active job set. A dispatch names exactly one operation, custom batch or minion. The publisher selects its queue accordingly:
const queueName = input.minionName
? QueueNamingUtils.buildMinionTickQueueName(input.applicationId, input.minionName)
: QueueNamingUtils.buildQueueName(input.applicationId, 'scheduled');
That selected implementation keeps a minion tick out of the backend’s ordinary scheduled-work queue. Both are still inside the application’s configured virtual host. The token signer names the target and work; the receiver verifies the scheduler’s signature before interpreting the instruction.
Bring up the queue owner before publishing
The receiving runtime declares its queue: the application backend owns the scheduled-work queue, and each minion owns its named tick queue. The scheduler checks that the destination already exists and refuses publication if it is absent; it does not create a replacement queue with guessed settings.
Repair the receiving runtime, queue topology or broker permissions before requesting fresh work. Queue existence alone does not prove a consumer is healthy, and a message retained by the broker can outlive its signed authorization.
Distinguish the stages when operating it
| Stage | What its evidence establishes |
|---|---|
| Schedule synchronization | The platform accepted the application’s declared jobs |
| Tick publication | The scheduler submitted the signed dispatch to the broker |
| Runtime execution | The appropriate backend or minion received and handled the work |
| Business result | The intended record, export or other effect actually exists |
A published tick is not a completed business job. Inspect the receiving runtime and resulting effect when diagnosing a missed export. A broker-refused virtual host enters bounded retry quarantine; it needs provisioning or permission repair, not repeated immediate attempts.
Know which failures retry
| Failure stage | Inherited behavior | What to inspect or supply |
|---|---|---|
| Configured schedule synchronization fails | Application startup continues; synchronization retries after 1 second with exponential backoff capped at 5 minutes, until success or shutdown | Check sync logs and manager connectivity. A running application does not prove that its schedules were accepted |
| Sync service is uninitialized or its manager is unconfigured | Synchronization is skipped without scheduling that retry | Correct initialization or manager configuration; waiting alone does not register jobs |
| Broker refuses a virtual host | Connection attempts for that host are quarantined with increasing delays, from 1 minute up to 30 minutes | Repair the host or publishing permission. This backoff is separate from application-job retry |
| A minion handler throws, or its tick fails verification | The consumer negatively acknowledges that delivery without requeueing it | Inspect the minion failure and resulting business state; the next scheduled tick is fresh work, not automatic replay of the failed transaction |
Successful minion handling acknowledges the tick. The no-requeue rule above describes the consumer’s explicit failure handling; it does not promise that broker or connection failures can never cause redelivery. The application owns recovery of an incomplete business effect, including deciding whether and how it is safe to replay it.
Scheduler replicas coordinate through a shared lease: the leader arms schedules and rechecks ownership before each scheduled tick; standbys disarm their tasks. A lease check is not end-to-end deduplication: a stalled publisher can race with takeover after passing the check. Application-declared schedules are reconciled through startup sync; administrative scheduler operations are a separate control surface. Keep handler retry/idempotency policy and recovery of interrupted work explicit.
When a runtime misses a tick
A signed tick has a five-minute token lifetime. The verifier allows 30 seconds of clock tolerance; a queued message is not an indefinitely reusable authorization to run the work.
| What happens | What the operator should expect |
|---|---|
| A runtime receives a tick after its accepted lifetime | Verification refuses the expired instruction before executing its work |
| Scheduled backend execution or verification fails | The consumer rejects without requeue; its scheduled dead-letter copy supports inspection |
| Minion tick processing fails | The consumer also rejects without requeue; it does not automatically retry that tick |
| A later scheduled occurrence arrives | The scheduler creates a fresh signed tick, not a replay of the missed business operation |
After an outage, inspect the receiving runtime and the business result before deciding what to recover. Reusing an expired token does not repair missed work. A catch-up action must deliberately select the missing work and avoid duplicating completed effects; the next cron occurrence alone does not establish that recovery happened.