Bond 1.0.0 is out — the first stable release. ![]()
After three release candidates and a good deal of dogfooding, Bond has reached 1.0.0. The SemVer stability guarantees described in the docs are now in force: the public API surface is frozen, and changes to it follow a real deprecation policy from here on.
def deps do
[{:bond, "~> 1.0"}]
end
What Bond is
Bond brings Design by Contract to Elixir. You write a function’s obligations and guarantees right next to the code they constrain, and Bond checks them at runtime with failure messages that tell you exactly what was violated and why:
defmodule Account do
use Bond
@pre sufficient_funds: amount <= account.balance, positive: amount > 0
@post drawn_down: result.balance == account.balance - amount
def withdraw(account, amount) do
%{account | balance: account.balance - amount}
end
end
Beyond @pre/@post, Bond gives you @invariant for struct modules (a property that must hold of every instance), check/1,2 for inline assertions, and old/1 for referring to a value as it was on entry. Contracts are conditionally compiled per environment — each kind (:preconditions, :postconditions, :invariants, :checks) can be true, false, or :purge, and :purge strips the contract code entirely so there is zero runtime cost in production.
Bond stays in its lane: it doesn’t replace typespecs, set-theoretic types, or ExUnit. It complements them with runtime-checked assertions over parameters, results, and state.
Because @invariants are machine-checkable, Bond can also drive them: Bond.PropertyTest.invariants_hold/2 runs randomized sequences of constructor/transformer/observer operations (via StreamData) and uses your invariants as the oracle across every reachable state — property-based testing for free, once you’ve stated the invariant. (Details in the docs.)
The getting-started guide is the best on-ramp.
What changed across the release-candidate cycle
The rc.1 announcement covered the bulk of the feature set — invariants, the concurrency guide, conditional compilation, library coexistence, corrected predicate typespecs. A few things landed after it that weren’t yet announced here:
- rc.2 — Bond can share a single module with other libraries that override
Kernel.@/1or wrap your functions (Norm, anything built ondecorator):use Bond, at_annotations: falseplus tolerance of externally-generated override clauses. Contract labelling was also unified on the single keyword-list form (@pre positive: x > 0). - rc.3 — the property-testing entry point was split into two clearly-named macros:
contract_holds/2for a single function and the newinvariants_hold/2for the stateful module-sequence form above. - rc.4 — a soundness fix for
@invarianton heterogeneous multi-clause functions: a struct clause’s pre-invariant could be silently skipped when a sibling clause matched a non-struct value. Now fixed.
The full history is in the changelog.
What 1.0.0 means for you
The point of 1.0.0 is that you can now depend on Bond’s public surface with confidence:
- Every name covered by the SemVer contract is enumerated in the public API surface guide — macros, attributes, predicates, the test helpers, telemetry, error structs, config keys, types. Internal namespaces are explicitly carved out.
- The stability guarantees guide spells out what patch / minor / major mean in practice, what’s explicitly excluded (compile-error text, generated-code shape, exception message text), and the deprecation policy.
- Compatibility is verified across Elixir 1.16–1.19 in CI.
What’s next
With 1.0 stable, the next thread of work is contract inheritance: letting a behaviour declare @pre/@post on its callbacks so that implementing modules inherit those contracts automatically (with protocols to follow). This is design-in-progress, not a promise of timing — if the idea interests you, early discussion is very welcome on the issue tracker.
Thanks
Bond is meaningfully better for the feedback from the original 2024 thread and the RC threads — thank you to everyone who kicked the tires, filed issues, and pushed back on the design. That input is exactly what the RC window was for, and it shaped what shipped today.
Feedback, bug reports, and ideas remain welcome here or at Issues · jvoegele/bond · GitHub.
Links
Original library announcement: Bond - Design by Contract for Elixir
RC1 announcement: Bond (design by contract for Elixir) - 1.0.0-rc.1 released






















