Docs Why Boundary Libraries Blog GitHub Get Started →
v1.0.1-alpha-22 — Now available

The Clojure framework
that ships the whole stack.

22 independent libraries. Enforced FC/IS architecture. One coherent stack, zero lock-in.

$ curl -fsSL https://get.boundary-app.org | bash
22
Independent Libraries
FC/IS
Enforced by Design
1.12
Clojure Compatibility
Zero
Vendor Lock-in
What's included

The full stack, built in.

Stop stitching together libraries. Every component follows the same patterns, tests the same way, and swaps via configuration.


Architecture

Enforced. Not suggested.

Every Boundary module follows Functional Core / Imperative Shell. The directory structure makes clean architecture the default — not a convention that erodes over time.

Imperative Shell
shell/
I/O · HTTP handlers · Persistence · Side effects
http.clj service.clj persistence.clj
Ports — Protocol Definitions
ports.clj
Interfaces only · Injectable adapters · No implementation
defprotocol
Functional Core
core/
Pure functions · Business logic · No I/O · No mocks needed
validation.clj domain.clj rules.clj

Enforced by directory layout + clj-kondo rules  ·  Every library follows the same structure


22 Libraries

Pick what you need.
Drop what you don't.

Each library is a standard deps.edn dependency, independently publishable to Clojars.


Real code

See the patterns. Feel the clarity.

Terminal
# Natural language module generation
$ bb scaffold ai "order module with customer, total, status"

 Schema defined       schema.clj
 Validation rules     core/validation.clj
 Persistence layer    shell/persistence.clj
 HTTP routes          shell/routes.clj
 Service layer        shell/service.clj
 Tests generated      test/core_test.clj

Generated 6 files in libs/order/
All tests passing: 12/12
schema.clj
(ns boundary.order.schema
  (:require [malli.core :as m]))

(def Order
  [:map
   [:id          :uuid]
   [:customer-id :uuid]
   [:total       [:and :decimal [:> 0]]]
   [:status      [:enum
                  :pending
                  :paid
                  :shipped
                  :delivered]]
   [:created-at  :instant]])
order/workflow.clj
(defworkflow order-workflow
  {:initial-state :pending
   :states        #{:pending :paid
                    :shipped :delivered
                    :cancelled}
   :transitions
   [{:from :pending
     :to   :paid
     :required-permissions [:finance]}
    {:from  :paid
     :to    :shipped
     :guard :payment-confirmed}
    {:from :shipped
     :to   :delivered}]})

; Pure core logic — no I/O, no mocks needed

Pure business logic

The entire state machine lives in core/ — no I/O, no side effects. Test every transition without a database or mock.

Audit trail by default

Every state change is recorded with who, when, and from/to state. Query with plain SQL.

Guards + permissions

Role-based guards and custom guard functions. The workflow rejects invalid transitions at the transition layer.

config.edn
;;; Development — zero setup, zero config
{:boundary/db-context
 {:adapter   :sqlite
  :db        "dev.db"}

 :boundary/cache
 {:adapter   :in-memory}

 :boundary/observability
 {:log-adapter  :stdout
  :err-adapter  :no-op}}

;;; Production — one key change each. Zero code changes.
{:boundary/db-context
 {:adapter   :postgresql
  :host      #env DB_HOST
  :pool-size 10}

 :boundary/cache
 {:adapter   :redis
  :uri       #env REDIS_URL}

 :boundary/observability
 {:log-adapter  :datadog
  :err-adapter  :sentry
  :dsn          #env SENTRY_DSN}}
routes.clj
;;; Cross-cutting concerns declared alongside the route.

{:path    "/api/admin/orders"
 :methods
 {:post
  {:handler      'handlers/create-order
   :interceptors ['auth/require-admin
                  'audit/log-action
                  'rate-limit/admin
                  'metrics/record-latency]}}}

;;; Service layer — one macro call, all telemetry automatic
(defn create-order [this order-data]
  (service/execute
    :create-order {:order order-data}
    (fn [{:keys [params]}]
      (order-core/prepare
        (:order params)))))

; Automatically instruments: structured logs, metrics,
; Sentry breadcrumbs, PII redaction. No telemetry code needed.

vs the alternatives

Not another toolkit.

Kit, Phoenix, Django, and Rails all require you to assemble and wire the pieces yourself. Boundary ships FC/IS enforcement, auto-admin UI, multi-tenancy, state machine workflows, full-text search, report generation, PII redaction, and framework-aware AI tooling — built in, consistent, following the same patterns across all 22 libraries.


Measurable ROI at every scale.

Numbers based on comparing Boundary to assembling a custom Clojure stack from scratch.


Built for every stage.

The ROI compounds. Small teams ship faster. Growing companies scale without chaos. Enterprises govern without mandates.


Up in minutes

From zero to running in three steps.

01
Bootstrap the starter
curl -fsSL https://get.boundary-app.org | bash
Requires curl, tar, and Babashka (bb). Downloads only starter essentials.
02
Set up the project
cd boundary-starter && bb setup
Configures environment, downloads deps, creates the SQLite dev database.
03
Start the REPL
export JWT_SECRET="change-me-dev-secret-min-32-chars" export BND_ENV="development" clojure -M:repl-clj
HTTP server on :3000, REPL-driven workflow, zero-config SQLite database.

Join the community.

Follow development on GitHub, chat on Clojurians Slack, and catch tutorials on YouTube.

GitHub Clojurians Slack YouTube Start Building