Skip to main content

Overview

We use Kubernetes CronJobs to trigger Restate service endpoints on a timer. Each cronjob is a tiny curl container that POSTs to the Restate Cloud ingress URL. Restate handles durable execution, retries, and idempotency — the cronjob just kicks it off.

Adding a new cronjob

Edit the environment values file for the target environment(s):
  • eks-cluster/helm-chart/restate/environments/staging-eu-central-1.yaml
  • eks-cluster/helm-chart/restate/environments/production001/us-east-1.yaml
Add a new entry under scheduledTasks.jobs:
scheduledTasks:
  jobs:
    my-new-job:
      schedule: "0 6 * * *"
      urlPath: 'hydra.v1.MyService/global/DoThing/send'
      idempotencyKey: 'my-job-$(date -u +%Y-%m-%d)'
      body: '{"someParam": "value"}'
Merge to main → ArgoCD deploys the new CronJob. Done.

Field reference

FieldDescription
scheduleStandard 5-field cron expression. All times are UTC.
urlPathRestate service path: hydra.v1.{Service}/{key}/{Handler}/send
idempotencyKeySent as idempotency-key header. Use shell date expansion to make it unique per run.
bodyJSON string payload for the service handler.

URL path format

hydra.v1.{ServiceName}/{key}/{HandlerName}/send
  • /send makes it an async (fire-and-forget) invocation
  • {key} can be static (global) or dynamic ($(date -u +%Y-%m-%d))

Idempotency keys

Use shell date expansion to generate unique keys per execution window:
PatternExample outputUse for
$(date -u +%Y-%m-%d)2026-03-18Daily jobs
$(date -u +%Y-%m)2026-03Monthly jobs
$(date -u +%Y-%m-%dT%H:%M)2026-03-18T14:30Sub-daily jobs
If Restate sees the same idempotency key twice, it deduplicates — pick a granularity that matches your schedule.

Existing jobs

JobScheduleWhat it does
quota-check0 15 * * *Daily quota verification
cert-renewal0 3 * * *Renews certificates expiring within 30 days
key-refill0 0 * * *Refills API key pools
scale-down-idle0 * * * * / */15 * * * *Scales down idle preview deployments (hourly staging, every 15min prod)

Runtime details

  • Image: curlimages/curl:8.12.1
  • Timeout: 300s per execution
  • Retries: 3 attempts (backoffLimit)
  • Concurrency: Forbid — won’t start a new run if previous is still running
  • History: 3 successful + 5 failed job records kept
  • Resources: 10m CPU / 32Mi memory
  • Auth: Bearer token from restate-cloud-credentials secret (AWS Secrets Manager)

Monitoring

Prometheus alert RestateCronJobFailing fires after 15 min of failures:
  • Staging: warning
  • Production: critical
Config: eks-cluster/helm-chart/observability/templates/prometheus-alerts-restate-cronjobs.yaml

Files

FilePurpose
eks-cluster/helm-chart/restate/templates/cronjobs.yamlHelm template that generates CronJobs
eks-cluster/helm-chart/restate/values.yamlBase values (jobs disabled by default)
eks-cluster/helm-chart/restate/environments/*.yamlPer-environment job definitions
eks-cluster/helm-chart/observability/templates/prometheus-alerts-restate-cronjobs.yamlAlerting rules