Systemd timers not running as expected

I have this in my nixos config:

  systemd.services."backups" = {
  path = [ pkgs.nix ];
    script = "/home/user/run_backup.sh";
    serviceConfig = {
      Type = "oneshot";
      User = "user";
    };
  };
  systemd.timers."backups" = {
    timerConfig = {
      OnUnitActiveSec = "12h";
      Persistent=true;
      Unit = "backups.service";
    };
    wantedBy = [ "timers.target" ];
  };

My expectation was that this would run every 12 hours from the last run and write the timestamp of the last run to disk, so that after waking from hibernation, the timer would be triggered again if 12 hours have passed. But from looking at the logs, I’m seeing it only run every 2-3 days, despite me using my laptop a few hours every day.

After reading the docs multiple times, I’m still confused why it’s not working. Could someone please point out what I’m missing?

From systemd.timer(5):

These are monotonic timers, independent of wall-clock time and timezones. If the computer is temporarily suspended, the monotonic clock generally pauses, too.

Yes, but also in the docs for persistent:

If true, the time when the service unit was last triggered is stored on disk. When the timer is activated, the service unit is triggered immediately if it would have been triggered at least once during the time when the timer was inactive.

Wouldn’t that make the timer respect passage of wall-clock time when the system isn’t powered on?

I don’t think so. “if it would have been triggered at least once during the time when the timer was inactive” sounds to me like it would not have triggered during suspend time since the monotonic clock was paused.

Okay, thanks I guess that explains the observed behavior. But pretty confusing documentation in my opinion.

The manpage also mentions:

WakeSystem=
           Takes a boolean argument. If true, an elapsing timer will
           cause the system to resume from suspend, should it be
           suspended and if the system supports this. Note that this
           option will only make sure the system resumes on the
           appropriate times, it will not take care of suspending it
           again after any work that is to be done is finished. Defaults
           to false.

           Note that this functionality requires privileges and is thus
           generally only available in the system service manager.

           Note that behaviour of monotonic clock timers (as configured
           with OnActiveSec=, OnBootSec=, OnStartupSec=,
           OnUnitActiveSec=, OnUnitInactiveSec=, see above) is altered
           depending on this option. If false, a monotonic clock is used
           that is paused during system suspend (CLOCK_MONOTONIC), if
           true a different monotonic clock is used that continues
           advancing during system suspend (CLOCK_BOOTTIME), see
           clock_getres(2) for details.

so either using that or an OnCalendar timer might get you what you want.