Docs

Schedules, grace and timezones

How FlatLyne decides when a ping is due, when a check is late or down, and how cron expressions, timezones and daylight saving time affect that.

This page explains how a check's schedule and grace period turn into a due time, when FlatLyne marks the check late or down, and how cron expressions behave across timezones and daylight saving time (DST).

Pick a schedule type

Every check has one of two schedule types. You pick it under Schedule type when you create a check.

Schedule typeNext due time after a success pingUse it when
Simple intervalThe ping time plus the Period.The job runs every N minutes, hours or days and you care about the gap between runs, not the clock time. For example, a queue drainer that runs every 15 minutes.
Cron expressionThe next time the cron expression matches after the ping, in the check's Timezone.The job runs at fixed clock times, such as 0 2 * * * for 02:00 every night. Use the same expression your crontab or scheduler uses.

Both types use a Grace period: how long FlatLyne waits past the due time before it marks the check Down.

A simple interval check counts real elapsed time, so it follows your job's actual ping times. A cron check is anchored to the clock, so it expects the job at the scheduled time no matter when the last ping arrived.

How late and down are decided

Only a success ping sets the due time. FlatLyne then compares the current time against it:

WhenStatusAlert
Before the due timeUpNone
After the due time, within the grace periodGrace (the ping is late)None
After the due time plus the grace periodDownFlatLyne alerts the project's channels

FlatLyne looks for late checks every 10 seconds, so a status change can lag the exact due time by up to about 10 seconds. A check that skips straight past its grace period between two passes goes from Up to Down directly.

Each kind of ping affects the due time differently:

PingStatus afterwardsDue time
SuccessUpRecomputed from the ping time, as described above.
/startUnchangedLeft as it was, so a run that starts and then hangs still goes late and down on time.
/fail or a nonzero exit codeDown right awayLeft as it was. The check stays Down until a success ping.

A New check has no due time until its first success ping, so it never goes late on its own. See Reporting failures for how to send /start and /fail.

Worked timeline: simple interval

Say backup-db-nightly has a Period of 1 day and a Grace period of 1 hour. The job sends a success ping when it finishes.

TimeWhat happensStatus
Mon 02:04Success ping. Next due time: Tue 02:04.Up
Tue 02:04The due time passes with no ping.Grace
Tue 02:06The job finishes two minutes later than yesterday and pings. Next due time: Wed 02:06.Up

If Tuesday's ping never arrives, the check goes Down at Tue 03:04 (02:04 plus 1 hour), and FlatLyne sends an alert.

Notice that the due time moves with each ping. If your job gets slower day by day, the deadline follows it, and every run that finishes later than the previous one spends a few minutes in Grace.

Worked timeline: cron expression

Now say backup-db-nightly uses the cron expression 0 2 * * * in UTC with a 1 hour Grace period. The job starts at 02:00, takes about four minutes, and pings when it finishes.

Time (UTC)What happensStatus
Mon 02:04Success ping. The next match after 02:04 is Tue 02:00.Up
Tue 02:00The due time passes while the job is still running.Grace
Tue 02:04The job finishes and pings. Next due time: Wed 02:00.Up

If Tuesday's ping never arrives, the check goes Down at Tue 03:00 (02:00 plus 1 hour).

Because the due time is the scheduled start time, a job that pings at the end of its run sits in Grace for the whole run, every time. That's expected and doesn't alert. It's why the grace period for a cron check has to cover the job's run time.

The next due time is always the next match strictly after the ping. If you run the job by hand at 01:59, the check expects its next ping at 02:00 the same day, so a manual run doesn't excuse that night's scheduled run.

Choose a grace period

The grace period is your tolerance for lateness. Too short and you get false alerts on slow runs; too long and a dead job goes unnoticed for longer.

  • Cron checks: set it longer than the job's longest normal run, plus some slack. A backup that usually takes 5 minutes and sometimes takes 25 is safe with a 1 hour grace period.
  • Simple interval checks: set it longer than the run-to-run variation in when the job pings, plus slack. A job that pings anywhere between 02:01 and 02:20 needs at least 20 minutes.
  • Jobs that run on local wall-clock time with a simple interval: add at least an hour, or switch to a cron schedule. See Daylight saving time below.

In the dashboard, the Period and Grace period pickers accept any value from 1 minute to 365 days.

The shortest schedule depends on the project owner's plan: 1 minute on Free, 30 seconds on Pro. FlatLyne rejects a shorter Period, or a shorter cron @every duration, when you create a check or edit its schedule. A five-field cron expression never runs more often than once a minute, so it's allowed on both plans. A check that pings every 30 seconds uses 2 of its 3 pings per minute, so adding a /start ping to every run goes over the limit.

Set the timezone

The timezone only matters for cron checks. A simple interval check counts elapsed seconds and ignores it.

  • Per check: pick a Timezone next to the cron expression when you create or edit a check. FlatLyne evaluates the expression in that timezone.
  • Project default: set Timezone under Settings → Project. New projects start in UTC. This value pre-fills the Timezone field when you create a cron check; changing it doesn't touch existing checks.

The dashboard offers these IANA timezones: UTC, America/New_York, America/Chicago, America/Los_Angeles, Europe/London, Europe/Berlin, Asia/Kolkata, Asia/Tokyo and Australia/Sydney.

The same Settings → Project page has Default period and Default grace period under Default Check Settings. New projects start with 1 day and 1 hour. They pre-fill the create-check form only.

Daylight saving time

FlatLyne evaluates cron expressions on the local wall clock of the check's timezone. When the clock jumps, some local times don't exist and others happen twice. Here's what FlatLyne actually expects in America/New_York, which springs forward on Sunday, March 8, 2026 and falls back on Sunday, November 1, 2026.

ExpressionSpring forward (Mar 8: 02:00 jumps to 03:00)Fall back (Nov 1: 01:00 to 01:59 happens twice)
30 2 * * *No run expected that day. After Saturday's 02:30 EST ping, the next due time is Monday 02:30 EDT.One run, at 02:30 EST.
0 2 * * *No run expected that day. The next due time after Saturday is Monday 02:00 EDT.One run, at 02:00 EST.
30 1 * * *One run, at 01:30 EST.Two runs: 01:30 EDT, then 01:30 EST an hour later.
0 * * * *01:00 EST, then 03:00 EDT. There's no 02:00.01:00 EDT, 01:00 EST, then 02:00 EST.

Europe/London behaves the same way at its own transition times. On Sunday, March 29, 2026, 30 1 * * * has no run; on Sunday, October 25, 2026, it matches at 01:30 BST and again at 01:30 GMT.

The fall-back row is the one that can surprise you. Say cleanup-tmp runs at 30 1 * * * in America/New_York with a 1 hour grace period, and your scheduler runs it only once that night. It pings at 01:31 EDT, so FlatLyne sets the next due time to 01:30 EST, one real hour later. No ping comes, the check goes Grace at 01:30 EST and Down at 02:30 EST, and you get an alert for a job that worked.

Simple interval checks have the opposite problem. A period of 1 day is exactly 86,400 seconds, not "same time tomorrow":

  • A ping on Saturday, October 31 at 02:04 EDT makes the next due time Sunday, November 1 at 01:04 EST, an hour earlier on the wall clock. If the job runs at 02:00 local time every night, its ping lands right at the end of a 1 hour grace period, so a slightly slow run alerts.
  • A ping on Saturday, March 7 at 02:04 EST makes the next due time Sunday, March 8 at 03:04 EDT, an hour later on the wall clock. Nothing alerts falsely, but a missed run takes an hour longer to detect.

Avoid false alerts on DST nights

If your job runs on local time, give the check a cron schedule with the same expression and timezone, and avoid scheduling it between 01:00 and 02:59 local time. Or run both the job and the check in UTC, which has no DST.

Change the schedule of an existing check

On the Checks list, select a check's period and grace cell to open Edit schedule. Saving replaces the schedule type, period or cron expression, timezone and grace period together.

Here's what happens when you save:

  • The check keeps its current status. A Down check stays Down until its next success ping.
  • The current due time stays as it is. The new period or cron expression takes effect from the next success ping.
  • The new grace period applies right away, to the current due time. Shortening it can move a late check to Down on the next pass.

If you switch a simple interval check to a cron expression, check the Timezone field before you save. It starts at the check's own timezone if it has one, otherwise your project's default timezone (UTC if neither is set).

Cron syntax

FlatLyne parses cron expressions with the robfig/cron v3 library's standard parser. An expression has exactly five fields, separated by spaces:

Field order
┌───────────── minute        (0-59)
│ ┌─────────── hour          (0-23)
│ │ ┌───────── day of month  (1-31)
│ │ │ ┌─────── month         (1-12 or JAN-DEC)
│ │ │ │ ┌───── day of week   (0-6 or SUN-SAT, 0 is Sunday)
│ │ │ │ │
0 2 * * *

Month and weekday names aren't case-sensitive. Use 0 for Sunday; 7 is rejected.

CharacterMeaningExample
*Every value* in the hour field means every hour.
?Same as *0 9 ? * MON
,A list of values1,15 in the day-of-month field means the 1st and the 15th.
-A range1-5 in the day-of-week field means Monday to Friday.
/A step*/5 in the minute field means every 5 minutes. 10-50/20 means 10, 30 and 50.

When you restrict both the day of month and the day of week, a day matches if either one matches. 0 9 13 * 5 runs at 09:00 on the 13th of every month and on every Friday, not only on Friday the 13th.

You can also use these shortcuts in place of the five fields:

ShortcutEquivalentRuns
@hourly0 * * * *At the start of every hour.
@daily or @midnight0 0 * * *At midnight every day.
@weekly0 0 * * 0At midnight every Sunday.
@monthly0 0 1 * *At midnight on the 1st of every month.
@yearly or @annually0 0 1 1 *At midnight on January 1.
@every 90mNone90 minutes after each success ping, like a simple interval. Takes a Go duration such as 30m or 1h30m.

FlatLyne doesn't support a seconds field (six-field expressions), L, W, #, H, or @reboot. As an alternative to the Timezone field, you can start the expression with CRON_TZ=Asia/Tokyo (or another IANA name); that prefix overrides the field.

Common expressions:

ScheduleExpression
Every 5 minutes*/5 * * * *
Every hour, on the hour0 * * * *
Every 6 hours, at 15 minutes past15 */6 * * *
Every day at 02:000 2 * * *
Weekdays at 09:000 9 * * 1-5 or 0 9 * * MON-FRI
Sundays at 03:000 3 * * 0
The 1st and 15th of each month at 09:000 9 1,15 * *
The 1st of each month at midnight0 0 1 * *

FlatLyne rejects an invalid cron expression or timezone when you save a check, and the form shows why. To see an expression's next run times before you save, try the cron expression tool.

What's next