This is primarily a performance release. Every hot-path change was benchmarked with criterium before it landed. It also adds a way to refresh a project’s framework-owned AGENTS.md after an upgrade, and fixes a handful of latent correctness bugs.
Changed: performance, tier 1 — compiled validators and protocol logging
-
Malli validators compiled once.
m/validate/m/explainwith a raw schema re-parse the schema and rebuild the predicate on every call — measured 8.6–9.9× overhead. All 121 static-schema call sites across 43 files (login, per-request handlers, per-WebSocket-message:prechecks) now usem/validator/m/explainerdefs compiled at namespace load.boundary.core.validationmemoizes compilation for schema-as-argument callers, and the scaffolder emits compiled validators in generated modules. -
Reflective logging removed.
boundary-platform’s reflective `(.info logger …)interop — fired on enter and leave of every request — is replaced withILoggerprotocol calls, measured ~90× per call.warn-on-reflectionis now enabled in those namespaces.
Changed: performance, tier 2 — single-pass conversion, caching, batching
-
boundary-platform: DB result keys are converted snake→kebab in the next.jdbc builder-fn (once per result set) instead of a second full per-row rebuild — ~1.7× on 100-row results. -
boundary-admin: entity config and table metadata are cached in the long-livedSchemaRepository— previously every admin page issued 2×Ninformation_schemaqueries. -
boundary-platform: static-resource middleware no longer does a classloader lookup on every request; duplicate param parsing dropped in favour of reitit’sparameters-middleware. -
boundary-i18n:resolve-markersuses a structural-sharing transform that returns original nodes when nothing changed — 82.4µs → 25.0µs (3.3×) on a 50-row table page. -
boundary-audience/boundary-user: N+1 write patterns batched into chunked multi-row INSERTs andexecute-batch!— a 50k-user audience drops from ~100k statements to ~102.
Changed: performance, tier 3 — CSRF fast paths, cached secrets, throttled heartbeat
-
boundary-platform:http-csrf-protectionshort-circuits before any binding/cookie work when CSRF is disabled (the default); correlation ids useThreadLocalRandominstead of the contended sharedSecureRandom; version headers are built once at wrap time. -
boundary-user: the JWT signing secret is resolved from the environment once per process instead of aSystem/getenvcall on every sign/verify. -
boundary-jobs: the worker Redis heartbeat is throttled to:heartbeat-interval-ms(default 5000 ms) instead of a round-trip per loop iteration.
Added: boundary agents update
boundary agents update (and the generated bb agents:update task) refreshes the framework-owned sections of a project’s AGENTS.md after a Boundary upgrade. The marker-delimited blocks are re-rendered from the installed CLI’s template and spliced in place; everything outside the markers — team notes, custom sections — is left untouched. --check exits 1 when the file is stale, for CI.
Fixed
-
boundary-platform: PostgreSQL session settings (statement_timeout,TimeZone=UTC,ApplicationName) now reach every pooled connection via JDBC URL properties — the previousSETstatements only affected the one connection that ran them, leaving the statement-timeout guard unset on the rest of the pool. -
build: the uberjar silently omitted 13 libraries because
build.cljhardcoded 9 source dirs; the list now derives from deps.edn:paths, so new libs are packaged automatically. -
boundary-email/boundary-external: theAttachmentschema used:bytes, which is not in Malli’s default registry — validation threw on every call (latent until validators were compiled at load). Fixed tobytes?. -
boundary-user:find-active-users-by-role,find-users-created-sinceandfind-users-by-email-domainran unboundedORDER BY … DESCwith no LIMIT; all three now default to the platform’smax-pagination-limit(1000).
Version alignment
All libraries bumped to v1.0.1-alpha-39 to maintain lockstep versioning.
Upgrade
Re-run the installer to pick up the latest release:
curl -fsSL https://get.boundary-app.org | bash
No migration required. Backward compatible — the performance changes preserve existing signatures, return values and security semantics.