Persistent Polling Behavior: Autonomous Condition Evaluation Without Schedulers
by Nick Clark | Published March 27, 2026
Persistent polling is a polling pattern that survives process restarts, host reboots, and substrate migrations without resetting its progress. The polling cadence is bounded by an explicit backoff envelope, the lineage of evaluated conditions and observed states is preserved across reboots, and the polling object resumes from its committed cursor when the host returns to service. The construction allows long-horizon condition evaluation without dependence on an external scheduler and without consuming continuous compute, replacing scheduler-resident state with object-resident state that travels with the polling subject itself.
Mechanism
A persistent polling object is a semantic object that carries within itself the predicate it is evaluating, the cadence at which the predicate should be evaluated, the cursor that records its progress, and the lineage of all prior evaluations. The object is dormant between evaluation cycles. It does not occupy a thread, a fiber, or a wakeup-timer slot in any external scheduler. When a wakeup is due, the host execution layer materializes the object, supplies it with the predicate inputs available at the current moment, and invokes its evaluation method. The method returns one of three outcomes: predicate satisfied, predicate not yet satisfied, or evaluation aborted due to insufficient input.
On predicate-satisfied, the object emits the downstream action it was created to dispatch, commits the satisfaction event to its lineage, and either terminates or transitions to a follow-on polling state depending on its declared lifecycle. On predicate-not-yet-satisfied, the object computes the next wakeup time using its backoff function, commits the failed evaluation and the next wakeup to its lineage, and returns to dormancy. On abort, the object commits the abort reason and either retries on a short retry cadence or escalates to its supervisor depending on the abort class.
The persistence property is achieved by serializing the object's complete state — predicate, cadence, cursor, lineage, next wakeup — into the substrate's durable store on every commit. When the host process restarts or the host machine reboots, a recovery routine reads all polling objects whose next wakeup falls in the past or near future, reconstructs them in memory, and resumes their evaluation from the cursor recorded in their last commit. Because the cursor is part of the committed state, no progress is lost across the restart, and no progress is duplicated: the cursor advances only on commit, and commits are atomic with respect to the durable store.
The lineage of evaluations preserved across reboots provides two distinct guarantees. The first is forensic: every evaluation outcome can be reconstructed from the lineage, so an operator inspecting a polling object after a long horizon can see exactly when each evaluation ran, what inputs it consumed, and what verdict it returned. The second is operational: the next-wakeup computation is a function of the lineage rather than a function of wallclock time alone, so the backoff schedule survives reboot without resetting to its initial value. A polling object that has been evaluating a condition every six hours for two weeks does not return to a one-second initial cadence after a host reboot.
Operating Parameters
The polling object is parameterized by an initial cadence, a backoff function, a maximum cadence, a deadline, and a supervisor binding. The initial cadence is the wakeup interval used immediately after creation and after any predicate-not-yet-satisfied evaluation that does not yet warrant backoff. The backoff function maps the count of unsatisfied evaluations and the elapsed time since creation onto the next wakeup interval. Common backoff functions include exponential with jitter, polynomial with floor, and adaptive functions that consult the rate of change of inputs to decide whether to lengthen or shorten the cadence.
The maximum cadence bounds the backoff function from above. Without an explicit maximum, an exponential backoff will eventually produce wakeup intervals on the order of years, which is rarely the operator's intent. The maximum cadence ensures that the polling object continues to make progress even on a long-horizon evaluation, with a worst-case wakeup interval bounded by the operator's policy. The deadline is an optional terminal time after which the polling object aborts regardless of predicate state, allowing the operator to express "evaluate this condition for at most thirty days, then escalate."
The supervisor binding identifies the upstream object or operator that should be notified of unusual outcomes — repeated aborts, deadline breach, or predicate satisfaction in domains where the result is itself a notification target. The supervisor binding is part of the durable state and survives reboot. A polling object whose creator has terminated continues to honor its supervisor binding by attempting delivery to the supervisor's last known address, falling back to a registry lookup if the address is stale.
A separate parameter family governs the lineage commitment cadence. Each evaluation commits at minimum the verdict and the next wakeup; in high-frequency polling deployments, the operator may elect to summarize batches of unsatisfied evaluations into a single committed entry to reduce write amplification. The summary commit retains the count of evaluations, the earliest and latest evaluation times, and a canonical hash of the inputs observed, so the forensic reconstruction remains complete even when the durable footprint is reduced.
Alternative Embodiments
In the canonical embodiment, the polling object is hosted on a single substrate and its durable state is committed to that substrate's local store. In a replicated embodiment, the durable state is committed to a quorum of substrates, and recovery after the loss of any single substrate is handled by re-materializing the object on a surviving substrate. The replicated embodiment trades commit latency for fault tolerance and is appropriate where the polling subject is load-bearing for downstream operations.
In a migratory embodiment, the polling object can move between substrates between evaluation cycles. Migration is triggered by load shedding on the current substrate, by data locality changes affecting the predicate inputs, or by operator policy. Because the durable state is self-contained, migration consists of committing the state on the source, transferring the committed state to the destination, and re-materializing on the destination. The cursor and lineage transfer intact; the evaluation cadence is unaffected.
In a federated embodiment, a polling object's predicate is evaluated cooperatively across multiple substrates, with each substrate evaluating a sub-predicate against its locally available inputs and the satisfied verdict reached only when all sub-predicates are satisfied. The federated form is appropriate for predicates that span data locality boundaries, including cross-tenant aggregations, multi-region condition checks, and hybrid cloud-edge deployments.
In a low-power embodiment suited to edge deployments, the substrate hosting the polling object may itself be intermittently powered. When the substrate wakes from a low-power state, it consults the polling objects whose next wakeup falls within the wake window and evaluates them; objects whose wakeup falls outside the window are deferred. The lineage records both the scheduled wakeup and the actual wakeup, so the forensic record reflects the substrate's duty cycle without distorting the polling cadence.
Composition With Adjacent Primitives
Persistent polling composes with the broader memory-resident execution architecture in three load-bearing ways. It composes with the substrate's lineage substrate by writing every evaluation outcome into the same append-only record that carries object creation, mutation, and termination events. The lineage thus presents a single ordered history per object, in which polling activity is visible alongside other lifecycle events, supporting the same forensic reconstruction guarantees as non-polling objects.
It composes with the substrate's wakeup scheduler by treating the scheduler as a hint provider rather than as a source of truth. The scheduler maintains an in-memory priority queue of upcoming wakeups for efficiency, but the durable next-wakeup field on each polling object is the authoritative cadence. If the scheduler is lost — process crash, host reboot, scheduler bug — the recovery routine rebuilds the queue from the durable next-wakeup fields without loss of progress.
It composes with the substrate's policy engine by allowing the policy engine to inspect and mutate polling objects through the same interface used for other semantic objects. A governance change that revokes the right to evaluate a particular predicate class causes the affected polling objects to be transitioned to a terminated state at their next evaluation, with the termination reason committed to lineage. The polling objects do not require a separate governance pathway.
Distinction From Prior Art
Conventional polling implementations rely on an external scheduler — cron, a job queue, an actor framework's wakeup timer — to track which conditions need to be evaluated and when. The scheduler holds the polling state, and the state is lost or corrupted when the scheduler fails. The construction described here inverts this relationship: the polling state lives on the polling object itself, and the scheduler is reduced to an in-memory hint cache that can be rebuilt from the objects.
Workflow engines such as Temporal and Cadence preserve workflow state across restarts but require a centralized event-history store and a centralized worker pool. The construction is decentralized: each polling object's state is self-contained, and recovery does not require consulting a central history. The substrate hosting the object can fail and recover without coordinating with peers, and the polling cadence resumes from the object's own committed cursor.
Reactive programming frameworks express polling-like behavior through observable streams and backoff operators, but the streams are process-resident and do not survive process restart. The construction provides the same compositional ergonomics — predicate evaluation, backoff, deadline, supervisor — while elevating the state to a substrate-resident form that survives the process lifecycle.
Embedded systems traditions encode persistent polling in firmware-resident state machines whose durability comes from the absence of a process boundary, but those state machines are bound to a specific device and cannot migrate. The construction generalizes the durability guarantee to a substrate-portable form while retaining the absence of an external scheduler.
Database-resident polling implementations, including pull-based change-data-capture systems and trigger-driven materialized view refreshes, achieve durability by encoding polling state as rows in the same database whose state they are observing. These implementations couple the polling lifecycle to the database lifecycle and require the database to act as the orchestrator. The construction described here decouples the polling object from any single observed resource, allowing the same polling object to evaluate predicates spanning multiple resources, multiple substrates, and multiple ownership domains, while retaining its own self-contained durability.
Finally, queue-based delayed-message systems achieve a similar surface behavior — a message reappears in a queue at a future time — but the message's payload is opaque to the queue, and the queue cannot evaluate the conditions under which the message should reappear. The construction makes the predicate first-class on the polling object, so the cadence and the evaluation are co-located and the lineage of evaluations is preserved on the same object that carries the predicate.
Disclosure Scope
The disclosure covers the polling pattern in which the polling state is resident on the polling object rather than on an external scheduler, the cadence is governed by a bounded backoff envelope, the cursor and lineage are preserved across host restart, and the object resumes evaluation from its committed cursor on recovery. Coverage extends to the parameter families described above, the alternative embodiments including replicated, migratory, federated, and low-power forms, and the composition with adjacent lineage and policy primitives. Embodiments that depend on an external scheduler for the next-wakeup cadence, that do not preserve cursor across restart, or that lack an explicit backoff bound fall outside the claimed scope. The disclosure is intended to support a non-provisional filing that elaborates the recovery protocol, the migration protocol, and the federated predicate evaluation protocol.