Skip to main content
A deployed function can carry a schedule. The platform calls it, so there is no worker of yours to keep alive.
heartbeat.py
Pair a schedule with a volume so the output has somewhere durable to land. A scraper feeding a dashboard is the usual shape.

Writing the schedule

Five-field unix cron with IANA timezone names, UTC by default. Both are validated at deploy time, so a typo is an error rather than a schedule that never fires.

Source is the truth

The schedule exists because the line exists. Delete schedule= and redeploy and the schedule is gone, which the deploy output confirms. cycls rm removes it with the deployment. There is no pause button and no separate object to keep in sync.

What can be scheduled

Bare functions only, the kind that deploy as named endpoints. Two cases fail at import with the fix in the message:
  • an app or agent with schedule=, since they serve HTTP. Schedule a function that calls them instead.
  • a function that takes port, since the port contract deploys a server and a schedule cannot fire one.

Semantics

Failed runs are retried, so write idempotent output. Date-keyed files like the example above make a double fire a harmless overwrite.
A run slower than its interval does not block the next one. If two runs must never race, take a lock file on the volume.
A single scheduled run has a thirty minute ceiling. Split longer work into slices, or have the scheduled function fan out with .map().
cycls logs <name> shows each one, with the same structured logging as any other call.

Next

Apps

Serve a FastAPI application with auth and per-user storage.