Some jobs run on a clock instead of in response to a request: refreshing a table of exchange rates, recomputing a daily rollup, warming a cache, syncing an external source. A scheduled function is a Function that Chalk invokes for you on a recurring schedule: declare a schedule in the decorator, and Chalk runs it at the cadence you specify, with the image, resources, secrets, and retry behavior you configured. There is no separate cron server to operate.

import chalkcompute

@chalkcompute.function(
    schedule="0 * * * *",                      # every hour, on the hour
    secrets=[chalkcompute.Secret.from_chalk_env("EXCHANGE_API_KEY")],
    cpu="1",
    memory="2Gi",
    retries=3,
)
def refresh_exchange_rates() -> None:
    import os
    import requests

    resp = requests.get(
        "https://api.example.com/v1/rates",
        params={"base": "USD"},
        headers={"Authorization": f"Bearer {os.environ['EXCHANGE_API_KEY']}"},
    )
    rates = resp.json()["rates"]
    # write the latest rates to your store
    ...

schedule and retries govern how and when the platform invokes the function; everything else configures the Scaling Group that hosts it, exactly as it would for an on-demand function. Scheduled jobs often do heavier work, such as nightly batch inference or periodic re-scoring of a dataset, and can request a GPU the same way:

@chalkcompute.function(
    schedule="0 3 * * *",      # daily at 03:00 UTC
    gpu="nvidia-l4",
    cpu="4",
    memory="16Gi",
)
def nightly_batch_inference() -> None:
    ...

​
Schedule syntax

schedule accepts either a crontab expression or a Chalk duration string. Use whichever reads more clearly for your cadence. All schedules are evaluated in UTC.

Crontab: five space-separated fields (minute hour day-of-month month day-of-week). Standard syntax is supported: *, lists (1,15), ranges (1-5), and steps (*/10).

ExpressionRuns
"*/10 * * * *"every 10 minutes
"0 * * * *"every hour, on the hour
"0 2 * * *"every day at 02:00 UTC
"0 0 * * 0"every Sunday at 00:00 UTC

Duration shorthand: a single interval, for simple cadences. Supported units are minutes (≤ 60), hours (≤ 24), and days (= 1), written as one value:

ShorthandRunsEquivalent crontab
"10m"every 10 minutes*/10 * * * *
"6h"every 6 hours0 */6 * * *
"1d"every day0 0 * * *

Shorthand intervals are aligned to clock boundaries, not to your deployment time: "6h" runs at 00:00, 06:00, 12:00, and 18:00 UTC. Anything longer or compound ("90m", "1h30m", "2d") must be written as a crontab expression.

@chalkcompute.function(schedule="0 2 * * *")   # nightly at 02:00 UTC
def nightly_rollup() -> None:
    ...

@chalkcompute.function(schedule="15m")         # every 15 minutes
def warm_cache() -> None:
    ...

​
Rules for scheduled functions

Because a scheduled function is invoked by the platform rather than a caller, two constraints apply and are enforced when the function is defined:

  • No inputs. A scheduled function must take no arguments. Have it read its own inputs from your sources.
  • Not a generator. A scheduled run has no caller to consume yielded values, so a scheduled function cannot yield. Return None (or a value) instead.

Everything else about a Compute Function still applies: custom images, resource requests, secrets, and retries all work exactly as they do for on-demand functions.

​
Observing runs

Each invocation appears in the Chalk dashboard with its status, logs, and resource usage, just like a manually invoked function. Emit logs from the body to make each run observable:

from chalk import chalk_logger

@chalkcompute.function(schedule="1h")
def refresh_exchange_rates() -> None:
    chalk_logger.info("refresh started")
    rates = ...  # fetch the latest rates and write them to your store
    chalk_logger.info("refreshed %s rates", len(rates))