When a transition consumes from multiple places, bindings determine which specific tokens are matched together.

Without bindings, a transition consuming from two places would fire on any combination of tokens from those places. You don't want to claim just any proxy for any target — you want one that supports the target's domain. Bindings express this: they declare that certain fields across tokens must correspond, similar to how foreign keys or join conditions relate rows across database tables.

This is how CPNs handle coordination. A transition that consumes from available_proxies and prioritized_targets with a binding requiring domain compatibility atomically claims a matching pair. The binding defines which combinations are valid, and the net only fires on valid combinations — no application-level locking needed.

In the claim demo, the submit transition consumes from both submissions and available_items. A binding declares that the submission's item name must match the item's name. Submitting "Widget" matches the Widget token — not the Fish, not the Sock. Mismatched combinations don't get filtered out by code; they simply never participate.

Bindings can express field equality, membership, and range conditions — anything that determines which tokens are structurally eligible to participate. The richer the binding language, the more conditions are handled by the system (analyzed, guaranteed complete) rather than checked in application code. This is the same additive vs. subtractive distinction: bindings are additive selection of valid token combinations. See guards for what happens with conditions that can't be expressed as bindings.

In practice

Bindings are the CPN equivalent of JOIN conditions. They make multi-resource coordination declarative rather than hand-coded. Every time you'd normally write application code to find matching records and lock them together — claiming a resource, assigning a task to an eligible user, matching an order to inventory — that's a binding.

See also