Skip to content
PynPyn

Scheduling internals

For the person who wants to know exactly when something will fire. The trigger and step pages describe the same rules from the task side.

Trigger kind Evaluated Reference date
Date, Employee Property (date, text, yes/no) On every HRIS or Employee File refresh for the employees that changed, and on a background pass for everyone roughly every six hours (at 7 minutes past 00:00, 06:00, 12:00 and 18:00 UTC) The matched date, or for text and yes/no the current day in the employee’s time zone
Recurring Hourly at 14 minutes past The run’s date
Group Change, Will be joining The moment a group membership is added or removed The current day
Buddy Assigned, Promoted to Manager, Change of Manager, Change of Location, Connected to Slack The moment the relation is set The current day
Form Submission The moment a submission completes The current day in the submitter’s time zone

Relation and group triggers are suppressed until the first HRIS load has finished, and relation triggers on messaging sources until the first messaging load has finished. When the workspace becomes ready, each published relation trigger is stamped with a “from” date of the following day and ignores changes before it.

A date trigger has five settings. The editor exposes two (This flow starts and the recurrence); templates can set the rest.

Setting Default Effect
Trigger date adjustment (This flow starts) 0 days (on the day of) Shifts the day the trigger fires relative to the reference date. Never moves the reference date.
Recurrence (year modulo) None (just once) Which anniversary years fire.
Excluded years None Exact years that never fire; every year after the first excludes year 1.
Trigger date window On-edge On-edge fires on exactly one day, the adjusted date. Within-window fires on every day between the reference date and the adjusted date, inclusive. Pre-onboarding uses within-window with a one-week adjustment, so it catches records that arrive late.
Reference date adjustment 0 days Shifts the reference date itself away from the employee’s date. The 90-day check-in template sets 90 days, so its steps schedule around day 90.

The order of operations: reference date = employee’s date + reference date adjustment; fire day = reference date + trigger date adjustment (or the window ending there); recurrence decides which years count. Time of day plays no part; a matching day fires whether the check runs at 00:00 or 23:59.

With years counted from the employee’s date (year 0 is the date itself):

Option Years
just once Only the original date, in its own year
every year 1, 2, 3, …
every year after the first 2, 3, 4, …
every other year 1, 3, 5, …
every 2 years 2, 4, 6, …
every 5 years 5, 10, 15, …
every 10 years 10, 20, 30, …

Year 0 never fires for a recurring option, which is why an anniversary flow and a start-date flow never coincide. A recurring trigger looks at the anniversary in the current year and one year either side, so adjustments on a recurring trigger must total less than a year. Birthdays are stored as month and day, with no year to count from, so they offer every year only.

A 29 February date fires on 28 February in non-leap years and on 29 February in leap years, for every recurrence option.

Each trigger carries Prevent repeat enrollments. When a trigger fires for someone it has fired for before, Pyn skips them unless the timeout has passed since the last time.

Rule Detail
Always reenroll Every firing enrols. Default for Form Submission and Custom trigger.
Never reenroll One enrollment per person, ever, including rehires. Default for the onboarding triggers, text and yes/no properties and No trigger.
Duration 1 hour, 1 to 7 days, 1, 3, 6 or 12 months.
One-day minimum Date and property triggers are re-checked several times a day, so Always reenroll and 1 hour are raised to 1 day for them and hidden from the list.
Manual enrollments Ignore the trigger’s timeout. The same person cannot be manually enrolled in the same automation twice within five minutes unless Flag as Test is on.

The “has fired before” record is written even when the automation is in Manual or Inactive mode and nobody is enrolled. Switching such an automation to Automated later does not enrol the people whose dates passed while it was switched off.

  1. The enrollment is created with its reference date (a calendar date, no time or zone).
  2. For each Enabled step in the version, an enrollment step is created: as draft in a paused enrollment, otherwise scheduled. A Disabled step is skipped. A step with Skip if overdue at enrollment whose send time is already past is created complete.
  3. Send time = reference date + the step’s offset, at the step’s hour and minute, in the step’s time zone: an explicit zone, or Recipient Timezone (the recipient’s profile time zone, falling back to the workspace zone). For a Slack channel, the channel has no zone and the workspace zone applies.
  4. If the resulting day is not one of the step’s Deliver on weekdays, the skipped-day rule applies: deliver anyway, move to the previous delivery day, or move to the next delivery day.
  5. A send time already in the past is sent on the next delivery pass.
  6. When a delivery is sent, its reminders and escalations are created as children of the delivery and scheduled from the send time.

Updating an enrollment to a new version repeats step 2 for new steps, recalculates steps still in draft or scheduled, and removes steps the version no longer has.