Callback¶
Core Idea¶
A callback is a named action handed off in advance, to be invoked later by someone other than the registrant, when a specified condition arises. The registrant relinquishes control over when and by whom the action is invoked; the invoker is given the action without needing to know the registrant's downstream reasoning. The pattern inverts the ordinary control flow — "I run this now" — into a deferred, conditional invocation — "if and when this condition holds, run this on my behalf." It is the structural device by which an agent commits to a future response without having to wait for the triggering event, and without retaining authority over the moment of action.
Three structural commitments are essential. Registration: a handler is given to a holder along with a binding condition that specifies when it should fire. Suspension: the registrant does not block waiting for the condition; control returns to the registrant immediately, and it proceeds with other work. Deferred invocation: when the condition is met, the holder invokes the handler — possibly in a different thread of control, possibly long after registration, in a context the registrant could not fully anticipate. These three together distinguish the callback from a simple instruction: the action is handed across a boundary of control, held by someone with better visibility of the triggering condition, and fired by that holder on the registrant's behalf.
The structure carries a consequential asymmetry. Because the handler is invoked by a foreign party at a moment the registrant does not choose, the registrant must reason in advance about what the handler is entitled to assume when it fires, how long the registration remains valid, and what happens if the condition occurs more than once or while another handler is still running. These are not implementation details but structural questions that any callback, in any substrate, must answer.
How would you explain it like I'm…
Ring When It's Time
Do-It-Later Instruction
Deferred Conditional Action
Structural Signature¶
the registrant handing off a named action — the handler (the deferred action) — the binding condition specifying when it fires — the holder who watches the condition and invokes the handler — the suspension releasing the registrant from synchronous waiting — the deferred foreign invocation at a moment the registrant does not choose
The pattern is present when each of the following holds:
-
A registrant. A party commits in advance to a future response without performing it now.
-
A named handler. A specific action is packaged and handed off, to be run later on the registrant's behalf.
-
A binding condition. A trigger is specified that determines when the handler should fire; the registrant defines what and under what condition but not when or by whom.
-
A holder with better trigger visibility. Another party — with closer sight of the triggering event — receives the handler and the condition and undertakes to invoke it.
-
Suspension. Control returns to the registrant immediately; it does not block waiting for the condition, and proceeds with other work.
-
Deferred foreign invocation. When the condition holds, the holder invokes the handler — possibly in a different control context, possibly long after registration — at a moment the registrant did not choose.
These compose into a structural asymmetry: because invocation is foreign and untimed, the registrant must answer, in advance, the four lifecycle questions the pattern forces — trigger semantics, invocation context, registration lifetime, and re-entrancy/ordering — and registration transfers authority to the holder to act in the registrant's name.
What It Is Not¶
- Not
feedback. Feedback routes a measured output back to modify input, closing a control loop continuously; a callback is a deferred conditional action handed to a holder who invokes it once (or per trigger). One regulates via a return path; the other defers an action across a control boundary. - Not
delegation_of_authority. Delegation grants ongoing authority to act broadly within a remit; a callback hands off a specific named action to be fired on a specified condition — narrower (one action, one trigger) though it does transfer authority for that act. Seedelegation_of_authority. - Not
indirection. Indirection is referencing a thing through an intermediary level; a callback is the temporal deferral of a named action to be invoked later by a foreign holder. Indirection redirects where; callback defers when and by whom. - Not
publish_subscribe. Publish-subscribe broadcasts events to many subscribers with no per-requester response; a callback is a registrant's own action lodged with a holder to be fired on the registrant's behalf — a directed handoff, not a broadcast. Seepublish_subscribe. - Not
controlled_reentry. Controlled reentry concerns re-entering a system or state safely; it appears in the callback only as the re-entrancy hazard (a handler firing while another runs), not as the pattern itself. - Common misclassification. Reaching for a callback where a blocking call would be simpler and safe — trading clean synchronous logic for asynchronous hazard with no decoupling benefit. The tell: does the registrant genuinely need to proceed before the condition fires? If it would simply wait anyway, the deferral adds lifecycle hazards for nothing.
Broad Use¶
- Asynchronous computation — event handlers, completion notifications, deferred continuations, and the observer pattern, where a handler is registered and fired later by a system with visibility of the event.
- Contract law — contingent clauses and standing instructions, where an action ("upon this condition, do that") is lodged in advance with a party who will execute it when the condition arises.
- Medicine — advance directives, where a patient registers a handler with the clinical system, to be invoked when specified conditions occur, in a context the patient cannot be present for.
- Operations and incident response — standing orders, runbooks, dead-man switches, and escalation policies, all pre-committed handlers held by an operational structure.
- Diplomacy and security — conditional commitments and rules of engagement, where a pre-committed response is held by an alliance or command structure against a triggering event.
- Personal coordination — "let me know when this arrives" or "ping me when it starts," handing a continuation to someone with better situational visibility than oneself.
Clarity¶
The pattern makes visible what would otherwise be hidden: who holds the continuation. Reasoning about a system shifts from "what does each actor do next?" to "who holds whose handlers, under what trigger?" That refactor reveals coupling and trust that are easy to miss when control flow is read as a single thread. A system that appears to be a sequence of self-directed steps is, once the callbacks are surfaced, a web of handlers lodged with various holders, each authorised to act in some registrant's name when a condition fires — and the web is where the real dependencies and failure modes live.
A second clarity dividend is the structured set of questions the frame forces. Because invocation is foreign — someone else decides when to fire — the analyst must reason about trigger semantics (when exactly is the condition met?), invocation context (what state is the handler entitled to assume at fire time?), registration lifetime (when does the handler expire?), and re-entrancy and ordering (can the handler fire while another is running?). These four questions structure the analysis whether the registrant is a piece of deferred computation, a patient with an advance directive, or a state with a defence commitment, and naming the pattern is what brings them to the surface. Left implicit, each is a latent failure; made explicit, each becomes a design decision.
Manages Complexity¶
The structural device decomposes a long blocking computation into what to do now and what to do later, given by a handler. Two parties no longer need to be synchronised in time: the registrant works on, the holder watches, and the invocation closes the loop only when warranted. This decoupling in time is the core complexity-management win — it removes the requirement that the registrant suspend itself until the event occurs, which is what lets a single thread of control attend to many pending conditions, and what lets a person, an organisation, or a state commit to a future response without standing idle until it is needed.
The same structure underlies large-scale concurrency on one side and standing-order delegation on the other, because both are instances of handing a continuation to a holder with better visibility of the trigger. The complexity savings are real: rather than maintaining an actor that waits, the system maintains a registry of handlers and the conditions that fire them, and the number of things actively waiting collapses to the number of holders watching. The cost of this saving is exactly the structural asymmetry — the registrant has given up control of the moment of action — which is why the lifecycle questions of idempotency, expiry, and re-entrancy are not optional refinements but the price of the decoupling, and why a callback that ignores them trades synchronous simplicity for asynchronous hazard.
Abstract Reasoning¶
Callback admits a clean structural analysis: registration is a commitment to act on a future event without specifying when; invocation is a foreign call into the registrant's commitment, fired by someone else's decision. This forces an analyst to reason about four things. Trigger semantics: when, exactly, is the condition met, and who judges that it is met? Invocation context: what state is the handler entitled to assume at fire time, given that the registrant has moved on? Registration lifetime: when does the handler expire, and must it be refreshed? Re-entrancy and ordering: can the handler fire while another is running, and what happens if it does? The same four questions structure the analysis whether the registrant is a deferred computation, a patient, or a state with a treaty.
From this structure several reusable inferences follow. Idempotency: if the holder might fire the handler twice, the handler must tolerate being run more than once, a hazard identical across deferred computation, duplicated standing orders, and at-least-once delivery. Expiry and re-registration: handlers stale out, so directives are refreshed, registrations are renewed, and commitments are re-affirmed. Trust transfer: registration gives the holder authority to act in the registrant's name, so the holder's failure modes — missed trigger, premature trigger, handler leaked to a third party — recur in every substrate. And the inversion-of-control diagnostic: when a system is hard to reason about, ask "who holds handlers I don't see?" — a probe that applies to debugging, auditing an organisation, and reading a contract alike. Each inference is reached from the structure rather than from any substrate, which is why the pattern reads as genuinely abstract, though its name leans on a programming origin.
Knowledge Transfer¶
The cross-domain payload is interventions, not just vocabulary, because the deferred-invocation-on-condition structure raises the same lifecycle hazards wherever it appears, and the same fixes resolve them. Idempotency requirements transfer directly: a handler that might fire twice must be safe to run twice, whether the doubling comes from at-least-once delivery, an order duplicated across a shift change, or a standing instruction that risks executing a transaction twice. Expiry and re-registration transfer: handlers that stale out must be refreshed, whether the refresh is an unsubscribed observer, a renewed directive, or a re-affirmed commitment. Re-entrancy hazards transfer: a handler that mutates shared state may fire while another is running, the same hazard in deferred computation, in operational cascades, and in legal triggers that fire during the processing of an earlier one.
Two further transfers complete the catalogue. Trust transfer is the recognition that registration confers authority on the holder to act in the registrant's name, so the holder's failure modes — missing the trigger, firing prematurely, or leaking the handler to an unintended party — are a shared cross-domain concern that any registrant must guard against. And the inversion-of-control diagnostic transfers as a debugging-and-auditing move: when a system feels hard to reason about, the right question is "who holds handlers I do not see?", which applies equally to tracing deferred computation, auditing an organisation's standing orders, and reading the contingent clauses of a contract. The four-question rubric — trigger semantics, invocation context, lifetime, re-entrancy — is itself the clean cross-domain checklist, and it is the load-bearing transferable artefact: applied to any deferred, conditional, holder-invoked action, it surfaces the hazards before they fire. The pattern's bare structure — a handler handed across a control boundary, held against a condition, fired by the holder, with the registrant released from waiting — is recognised in computation, law, medicine, operations, diplomacy, and personal coordination alike, though its programming-derived name gives it a mild origin lean that places it just off the purely structural end of the spectrum.
Examples¶
Formal/abstract¶
An event handler registered with an asynchronous I/O system is the origin case and exhibits the full lifecycle. The registrant handing off a named action is application code that wants to react when a network request completes. The handler is the function it packages — "when the response arrives, parse it and update the cache." The binding condition is the completion of the I/O operation. The holder with better trigger visibility is the event loop or runtime, which alone can see when the socket becomes readable. The suspension is the core move: rather than blocking on the socket, the registrant returns immediately and proceeds with other work, so a single thread can have thousands of handlers registered against thousands of pending conditions. The deferred foreign invocation is the event loop calling the handler later, possibly long after registration, at a moment the registrant did not choose. The structural asymmetry then forces the four lifecycle questions, each a real design decision. Trigger semantics: is the condition "response received" or "response fully buffered"? Invocation context: what state may the handler assume, given the registrant has moved on — has the cache it intends to update been torn down? Registration lifetime: does the handler expire if the response never arrives (a timeout), and must it be unsubscribed to avoid a leak? Re-entrancy and ordering: can the handler fire while a previous handler is still running, mutating shared state? The reusable inferences follow: idempotency (under at-least-once delivery the handler may fire twice and must tolerate it), expiry (a stale registration must be cleaned up), and the inversion-of-control diagnostic — when the asynchronous code is hard to trace, ask "who holds handlers I don't see?"
Mapped back: The application is the registrant, the completion function is the handler, request-completion is the binding condition, the event loop is the holder, non-blocking return is the suspension, and the later call is the deferred foreign invocation — the callback in its asynchronous-computation home, with the four lifecycle questions as design decisions.
Applied/industry¶
A medical advance directive instantiates the identical structure in healthcare, with a patient as the registrant. The registrant handing off a named action is a patient who, while competent, specifies care decisions for a future in which they cannot decide. The handler is the directive's instruction — "if I am in an irreversible coma, do not resuscitate." The binding condition is the specified clinical state. The holder with better trigger visibility is the clinical team, which alone can observe whether the triggering condition has arisen — the patient cannot be present to judge it. The suspension is exactly the value of the instrument: the patient does not have to be continuously present and deciding; they commit a response in advance and proceed with life, the human analogue of releasing the registrant from synchronous waiting. The deferred foreign invocation is the clinical team enacting the directive when the condition holds, in a context the patient could not fully anticipate. The same four lifecycle questions structure the analysis and are the source of real-world hazards. Trigger semantics: when exactly does "irreversible coma" obtain, and who judges it? Invocation context: what may the directive assume about the state of medicine or the patient's other conditions at fire time? Registration lifetime: directives stale out and must be periodically re-affirmed (the expiry-and-re-registration hazard, identical to an unsubscribed observer). Re-entrancy and ordering: what if a second condition fires while the first is being acted on? The trust-transfer inference is sharp here — registration gives the clinical team authority to act in the patient's name, so the holder's failure modes (missing the trigger, firing prematurely) are exactly the cross-domain concern. The same deferred-invocation-on-condition structure governs a contract's contingent clause (lodged in advance with a party who executes it when the condition arises), an operational dead-man switch, and a "ping me when the shipment arrives" personal-coordination handoff.
Mapped back: The patient is the registrant, the directive is the handler, the clinical state is the binding condition, the care team is the holder, not-having-to-be-present is the suspension, and the team enacting the directive is the deferred foreign invocation — the callback structure in medicine, where registration transfers authority to act in the registrant's name.
Structural Tensions¶
T1 — Synchronous Simplicity versus Asynchronous Decoupling (temporal). The callback buys time-decoupling — the registrant proceeds without waiting — at the cost of the four lifecycle hazards (trigger semantics, context, lifetime, re-entrancy) that synchronous waiting never incurs. The boundary is whether the decoupling is worth its hazard price. The characteristic failure is reaching for a callback where a blocking call would be simpler and safe, trading clean synchronous logic for asynchronous hazard with no decoupling benefit actually needed. Diagnostic: does the registrant genuinely need to proceed before the condition fires? If it would simply wait anyway, the deferral adds the lifecycle hazards for nothing.
T2 — Registrant Control versus Holder Authority (coupling). Registration transfers authority to the holder to act in the registrant's name, at a moment and possibly a context the registrant does not choose. The boundary is the handoff of control. The failure mode is registering a handler without reckoning the holder's failure modes — a missed trigger, a premature fire, a handler leaked to a third party — treating the holder as a passive trigger rather than an agent now empowered to act for you. Diagnostic: what can the holder do wrong with this authority, and what is the blast radius if it fires the handler at the wrong time or hands it on? The registrant has ceded the moment of action and must guard against the holder's failures.
T3 — Single Fire versus Repeated Invocation (measurement). A handler may be invoked once or, under at-least-once delivery or duplicated standing orders, more than once — and a handler safe to run once may corrupt state if run twice. The boundary is invocation multiplicity. The failure mode is writing a handler assuming exactly-once firing when the holder may fire it repeatedly, so a duplicated invocation executes a transaction or side effect twice. Diagnostic: can the holder fire the handler more than once? If so the handler must be idempotent — safe under repetition — and assuming single-fire where the delivery guarantee is at-least-once is the recurring asynchronous hazard.
T4 — Live Registration versus Stale Handler (temporal). Registrations stale out: the handler captured assumptions about a context that may no longer hold when it finally fires, and a registration left active past its validity leaks or misfires. The boundary is the registration lifetime. The failure mode is registering a handler with no expiry, so it fires against a torn-down context (a cache that no longer exists, a medical situation medicine has moved past) or lingers as a leak. Diagnostic: when does this registration expire, and must it be refreshed? A handler with an unbounded lifetime is a latent misfire whenever the world it assumed has changed since registration.
T5 — Re-entrancy versus Isolated Execution (coupling). Because invocation is foreign and untimed, a handler may fire while another handler is still running, mutating shared state mid-flight. The boundary is whether concurrent invocations can overlap. The failure mode is writing a handler as if it runs in isolation when re-entrancy lets it interrupt itself or another handler, corrupting shared state — the same hazard in deferred computation, operational cascades, and legal triggers firing during an earlier one's processing. Diagnostic: can this handler be invoked while a prior invocation is still in progress, and does it touch shared state? Where overlap is possible, isolated-execution assumptions break and re-entrancy must be guarded.
T6 — Visible Control Flow versus Hidden Continuations (scopal). The pattern's clarity dividend — surfacing who holds whose handlers — is also its hazard: a system read as a single thread of self-directed steps is actually a web of continuations lodged with various holders, and the dependencies hide in that web. The boundary is between the visible flow and the registered handlers. The failure mode is reasoning about a system from its apparent sequential logic while invisible callbacks fire and act, so the real coupling and failure modes are never in view. Diagnostic: who holds handlers I do not see? The inversion-of-control probe is the cure — when a system is hard to reason about, the hidden continuations, not the visible steps, are usually where the behaviour actually lives.
Structural–Framed Character¶
Callback sits on the structural side of the structural–framed spectrum, at the mixed-structural mark — aggregate 0.3. The pattern is genuinely abstract: a named action handed off in advance to a holder who invokes it later, on a specified condition, releasing the registrant from synchronous waiting. That deferred-invocation-on-condition structure — registrant, handler, binding condition, holder, suspension, foreign invocation — is recognised rather than imported wherever an agent commits a future response across a control boundary, which holds the aggregate near the structural end.
Two diagnostics read fully structural. Evaluative_weight is 0: the deferral mechanism carries no inherent approval — registering a handler is neutral structure, neither good nor bad until you say what it does. Human_practice_bound is 0 because the pattern runs in substrates with no human practice — an event handler registered with an asynchronous I/O system, fired by the event loop in a different control context — and its lifecycle inferences (idempotency, expiry, re-entrancy) are stated about the structure, not any human role. The three residual 0.5 scores record only a programming-origin film. Vocab_travels is 0.5 because the term "callback" and its companion vocabulary (registration, handler, invocation, re-entrancy) lean on a programming context that needs light translation into a medical advance directive or a legal contingent clause, even though the structure beneath ports cleanly. Institutional_origin is 0.5 because the named pattern arose in CS asynchronous control rather than as a pre-existing formal regularity. Import_vs_recognize is 0.5 because invoking it brings a control-flow lens — ask who holds whose handlers, work through the four lifecycle questions — though what it names is a deferred-handoff structure already present. The genuinely abstract core and the two zeros keep it structural; the programming-derived vocabulary is the only thing lifting the aggregate off zero, exactly as the mixed-structural 0.3 records.
Substrate Independence¶
Callback is a strongly substrate-independent prime — composite 4 / 5 on the substrate-independence scale. The deferred-invocation-on-condition structure is genuinely abstract — a registrant hands off a named action, a holder with better trigger visibility invokes it later on a binding condition, and suspension releases the registrant from synchronous waiting — and it is recognised rather than imported across asynchronous computation, contract-law contingent clauses, medical advance directives, operational standing orders and dead-man switches, diplomatic conditional commitments, and everyday "ping me when it arrives" coordination. The breadth crosses the human/non-human line: an event handler registered with an asynchronous I/O system is fired by the event loop in a different control context, and the lifecycle inferences (idempotency, expiry, re-entrancy) are stated about the structure, not any human role. The transfer is a concrete intervention catalogue, not just vocabulary: the four-question rubric — trigger semantics, invocation context, lifetime, re-entrancy — is the load-bearing cross-domain checklist, and the idempotency, expiry, and trust-transfer hazards recur identically whether the registrant is deferred computation, a patient, or a state with a treaty. What holds it short of 5 is a programming-derived name and companion vocabulary (registration, handler, re-entrancy) that lean on a programming context and need light translation into a medical or legal setting, even though the structure beneath ports cleanly.
- Composite substrate independence — 4 / 5
- Domain breadth — 4 / 5
- Structural abstraction — 4 / 5
- Transfer evidence — 4 / 5
Relationships to Other Primes¶
Parents (1) — more general patterns this builds on
-
Callback is a kind of, typical Delegation of Authority
The file: a callback is 'a narrow, mechanical special case of authority transfer: one action, one condition, no judgment' — registration transfers authority to the holder to act in the registrant's name. A specialization of delegation_of_authority (which grants broad ongoing discretion). Tentative — the file walls them sharply.
Path to root: Callback → Delegation of Authority → Authority
Neighborhood in Abstraction Space¶
Callback sits in a sparse region of abstraction space (64th percentile for distinctiveness): few abstractions share its structure, so a faithful description tends to retrieve it precisely rather than landing on a neighbor.
Family — Deferred Binding & Frames (9 primes)
Nearest neighbors
- Implementation Intention — 0.76
- Script — 0.70
- Authority Handoff — 0.69
- Compellence — 0.69
- Identity-Preserving Modification — 0.69
Computed from structural-signature embeddings · 2026-06-14
Not to Be Confused With¶
The most instructive confusion is with feedback, because both route a system's behaviour through a return-and-respond structure, yet they differ in what is returned and what is done with it. Feedback routes a measured output back to modify the input, closing a continuous control loop in which the system's own behaviour drives its next behaviour — the defining feature is the closed loop and the ongoing regulation it enables (stabilisation, amplification, oscillation). A callback routes a named action across a control boundary to a holder, who invokes it later when a condition fires — the defining feature is deferred, conditional, foreign invocation, not a closed regulatory loop. A feedback loop runs continuously and is about correction toward a reference; a callback fires discretely (once, or per trigger) and is about deferring an action until a condition holds. They can co-occur — a feedback controller might register a callback to be notified of a threshold crossing — but the callback is the deferral mechanism, not the loop. Conflating them imports regulatory-loop reasoning (gain, delay, sign) into what is really a lifecycle-of-deferred-invocation question (trigger semantics, expiry, re-entrancy), or vice versa.
A second genuine confusion is with delegation_of_authority, and here the relationship is genuine overlap with a sharp boundary. Both involve handing responsibility to another party who will act on one's behalf, and registering a callback does transfer authority to the holder to invoke the handler in the registrant's name. But delegation grants ongoing, discretionary authority within a remit — the delegate decides how to act across a range of situations, exercising judgment. A callback hands off a single, specified action to be fired on a single, specified condition — the holder is not exercising discretion over what to do, only watching for the trigger and invoking the pre-packaged handler. The callback is thus a narrow, mechanical special case of authority transfer: one action, one condition, no judgment. Treating a callback as broad delegation over-grants the holder discretion it does not have; treating genuine delegation as a callback under-models the delegate's judgment and remit. The advance directive example sits exactly on this line — the patient delegates no general medical discretion (that would be a healthcare proxy, closer to delegation), but registers a specific handler ("if irreversible coma, do not resuscitate") fired on a specific condition.
A third worth drawing is against publish_subscribe. Both defer action until an event occurs and both decouple the party that detects the event from the party that responds, which makes them easy to merge. The difference is the directedness and ownership of the action. In publish-subscribe, a publisher broadcasts events to many subscribers with no per-requester response and no notion of acting "on the publisher's behalf" — subscribers independently decide what to do with the event. In a callback, the registrant's own action is lodged with a holder to be fired on the registrant's behalf — a directed handoff of a specific continuation, not a broadcast. The callback's holder acts for the registrant; the publish-subscribe broadcaster does not act for the subscribers at all. Mistaking a callback for pub-sub loses the trust-transfer and the on-whose-behalf authority that make the callback's lifecycle hazards (the holder firing prematurely, leaking the handler) the registrant's concern.
For a practitioner the distinctions decide which hazards apply. Confusing the callback with feedback imports loop-tuning reasoning where lifecycle reasoning is needed; confusing it with delegation_of_authority mis-scopes the authority transferred (broad discretion versus one triggered action); and confusing it with publish_subscribe loses the on-whose-behalf direction that makes the holder's failures the registrant's risk. Asking "is a specific named action being deferred to a holder who will fire it on my behalf when a condition holds?" is what identifies a genuine callback among its neighbours.
Solution Archetypes¶
No catalogued solution archetypes reference this prime yet.