Why Boundary?
Boundary exists to make Clojure web applications feel deliberate instead of improvised.
The problem Boundary solves
Clojure is excellent for reliable systems, but the ecosystem leaves a lot of assembly work to every new project. Teams end up wiring together Ring, Reitit, next.jdbc, Malli, Integrant, auth libraries, and a few more moving parts before they can start building. Then they reinvent the same things again: authentication, pagination, validation, admin screens, module layout, and test structure.
Boundary packages those decisions into one coherent framework, so you do not have to rebuild the same foundation every time. The rule is to keep the Functional Core / Imperative Shell pattern visible everywhere, not just in the README.
For developers: 22 composable libraries
Use just boundary-core for validation utilities in an existing app, or compose the full stack with JWT + MFA auth, auto-generated CRUD UIs, background jobs, multi-tenancy, real-time WebSockets, and more.
Every library follows the same FC/IS structure, so a Boundary codebase feels familiar fast.
Ship faster with the scaffolder
bb scaffold ai "product module with name, price, stock"
The scaffolder generates fully structured modules in seconds. The admin UI can build CRUD screens from your schema, observability is built in, and declarative interceptors keep the plumbing out of your way.
Zero lock-in
Each library is a standard deps.edn dependency. Swap what doesn’t fit. If you do not need multi-tenancy, skip boundary-tenant. If you prefer a different cache backend, implement the cache port you need.
The FC/IS guarantee
Boundary enforces a clean separation between pure code and code that touches the outside world:
libs/{library}/src/boundary/{library}/
├── core/ ← Pure functions only. No I/O, no logging, no exceptions.
├── shell/ ← I/O, validation, persistence, HTTP, services.
├── ports.clj ← Protocol definitions (interfaces).
└── schema.clj ← Malli validation schemas.
That gives you business logic that is:
-
Fast to test — no mocks needed for core functions
-
Easy to reason about — given the same input, always the same output
-
Safe to refactor — the type system and tests catch regressions immediately
Compared to alternatives
| Property | Boundary | Pedestal | Luminus |
|---|---|---|---|
Enforces FC/IS |
Yes |
No |
No |
Scaffolder |
Yes (AI-assisted) |
No |
Partial |
Admin UI |
Auto-generated |
No |
No |
Library granularity |
22 independent libs |
Monolithic |
Template-based |
Multi-tenancy |
Built-in |
No |
No |