English · 00:25:53
Jan 27, 2026 12:25 AM

Real-world Clojure: Lessons from Growing a Team and a Codebase - Assum

SUMMARY

Erik, a veteran Clojure developer at Ardoq, discusses eight years of scaling the backend team from two to 20 developers, tripling the codebase, migrating databases, hiring strategies, and minimizing cognitive load for maintainable software.

STATEMENTS

  • Ardoq's Clojure backend has grown significantly over eight years, evolving from a Java-like application to idiomatic Clojure while migrating from MongoDB to Postgres.
  • The company's engineering motto emphasizes development speed over time, prioritizing maintainable code for consistent long-term productivity.
  • Cognitive load theory, as coined by John Sweller, divides into intrinsic (business problems), germane (learning the codebase), and extraneous (accidental complexity to avoid).
  • Early Clojure code from 2012 at Ardoq used outdated frameworks like Noir, featuring macros and flexible parameters that increased cognitive load through poor readability.
  • The current codebase totals 156,000 lines of production code with an equal amount of tests, running 3,200+ tests in parallel across 35 machines in 11 minutes from merge to production.
  • As a monolith, the codebase simplifies understanding dependencies and refactoring, avoiding the complexities of microservices.
  • Norris numbers suggest that codebase organization strategies must change at each order of magnitude in size, from single files for 1KLOC to structured approaches for 200KLOC.
  • Chesterton's fence principle advises understanding the purpose of existing code before altering it, preventing unintended disruptions.
  • Anonymous functions in functional programming obscure intent by focusing on "what" without explaining "why," increasing extraneous cognitive load.
  • Higher-order functions, when custom and bespoke, force developers to trace implementations, unlike standard ones like map or reduce, leading to unnecessary complexity.

IDEAS

  • Hiring Clojure developers yields fewer but higher-quality applicants due to the tight-knit community, easing access to skilled talent without broad recruitment challenges.
  • Onboarding scales inversely with team size; adding one person to a small team integrates seamlessly, but larger teams require structured approaches to maintain knowledge flow.
  • Transducers in Clojure reduce cognitive load by decoupling data conveyance, allowing simpler tests without full async setups and clarifying code intent.
  • Applying DRY to orchestration code, rather than just business logic, can lead to over-abstraction and pain; repetition in wiring is often preferable for readability.
  • Deep call stacks with side effects and parameter mutations overload working memory, as humans track only 4-7 items, making shallow stacks essential for comprehension.
  • Only 2.2% of feature lead time involves actual coding; the rest is upstream processes, highlighting that Clojure's productivity gains are limited without team and process improvements.
  • Providing maximum context to developers by letting them interact directly with stakeholders fosters ownership and better decision-making at forks in the road.
  • A culture of ownership empowers engineers to fix problems proactively, including improving management, turning passive roles into active contributions.
  • Weekly unstructured one-on-ones build trust through relationships, enabling early issue resolution and reducing escalation of difficulties.
  • Clean codebases preserve mental capacity for product development, unlike gnarly JavaScript, allowing engineers to contribute beyond coding.

INSIGHTS

  • Minimizing extraneous cognitive load through readable code structures directly enhances overall team productivity by freeing mental resources for intrinsic business challenges.
  • Scaling codebases requires adaptive organization strategies at magnitude thresholds, ensuring maintainability without rigid initial plans that fail at growth.
  • Clojure's community tightness transforms hiring from a bottleneck into an advantage, prioritizing quality over quantity in talent acquisition.
  • Direct stakeholder engagement builds developer autonomy and ownership, reducing managerial intermediaries and accelerating informed decision-making.
  • Trust cultivated via consistent personal interactions sustains high retention, as relational bonds mitigate remote work isolation and foster collaborative joy.
  • Prioritizing development speed over time integrates refactoring into daily workflows, preventing technical debt accumulation in growing monoliths.

QUOTES

  • "Development speed over time which means that we need to produce code that is maintainable and it's not about just getting the feature out but we need to be able to do that consistently over time."
  • "If you walk across a field and there's a fence and you see no reason for this fence to be there, you cannot remove that fence until you understand why it was put there in the first place."
  • "The functions that you pass to map filter and reduce that is your way of teaching Clojure standard library about your domain."
  • "When you're unsatisfied with your manager, it is on you to make your manager better. And rather than just sit there and wait for someone to do that for you."
  • "If you've been down into the gnarliest bits of JavaScript code and you come up you are drained you cannot think about product development but if you have like a sane codebase a sane language uh then you have spare capacity to do the stuff that really matters to your company."

HABITS

  • Using Emacs as the primary editor since the late 1980s, adapting to features like Font Lock despite initial resistance.
  • Contributing to open-source Clojure projects by fixing easy bugs in CLJ Commons libraries to maintain them for production use.
  • Conducting weekly unstructured one-on-one meetings with team members to build relationships and address issues early.
  • Refactoring code incrementally during daily work rather than backlog items, ensuring ongoing maintainability.
  • Starting the day with diverse tasks like frontend refactoring, one-on-ones, resource planning, and backend coding to balance interests.

FACTS

  • Ardoq's Clojure backend codebase began with Grails in 2012 and switched to Clojure on June 15th, growing to 156,000 lines of production code.
  • The company runs 3,200 tests on every commit in parallel across 35 machines, achieving deployment to production in about 11 minutes via GitHub Actions.
  • A study from Nationwide Insurance, referenced in The Unicorn Project, shows only 2.2% of feature lead time is spent on actual coding by developers.
  • Ardoq has scaled to 250+ employees, with 60 in engineering and 34 in product, approaching $50 million in annual recurring revenue as a SaaS enterprise architecture firm.
  • Clojure 1.12 introduced the "halt-when" transducer, enabling conditional stopping in data processing pipelines without complex loops.

REFERENCES

  • John Sweller's cognitive load theory.
  • Chesterton's fence principle.
  • The Unicorn Project by Gene Kim, citing Nationwide Insurance study.
  • Noir web framework (pre-Ring).
  • Liberator library for resource APIs.
  • Core.async and transducers in Clojure.
  • Clojure Design podcast by Kristoff Nyman.

HOW TO APPLY

  • Assess codebase for extraneous cognitive load by identifying anonymous functions and naming them to reveal domain intent, then refactor reduces or maps accordingly.
  • Evaluate call stacks for depth; inline single-use functions and consolidate side effects to keep hops under seven, preserving working memory.
  • Organize hiring by leveraging Clojure community networks on Slack or conferences, screening for quality over volume to attract aligned developers.
  • Implement onboarding with pair programming for small teams, gradually introducing codebase sections like recent AI chunking examples using transducers.
  • Foster team ownership by encouraging direct stakeholder talks, followed by autonomy in solutions, checked via weekly one-on-ones for trust-building.

ONE-SENTENCE TAKEAWAY

Prioritize minimizing cognitive load in code and team practices to sustain development speed and foster ownership in growing Clojure organizations.

RECOMMENDATIONS

  • Refactor incrementally during feature work to embed maintainability, avoiding backlog delays that accumulate technical debt.
  • Name higher-order functions explicitly when custom, favoring readable repetition over abstract DRY violations that obscure orchestration.
  • Build trust through unstructured weekly one-on-ones, empowering teams to address issues proactively and enhance retention.
  • Provide full context by routing developers directly to stakeholders, boosting ownership and decision quality without managerial bottlenecks.
  • Use transducers for async data processing to simplify testing and reduce setup complexity, clarifying intent in onboarding code.

MEMO

In the bustling world of enterprise architecture software, where scalability meets innovation, Erik, a seasoned Clojure engineer from Oslo-based Ardoq, has witnessed a quiet revolution. Over eight years, he helped transform a nascent backend team of two into a robust force of 20, while the codebase ballooned to 156,000 lines—matched by an equal volume of tests. Ardoq, now a 250-employee SaaS powerhouse nearing $50 million in annual revenue, credits its success to a mantra: development speed over time. This isn't about hasty features but crafting maintainable code that endures, a principle Erik illustrates with the company's shift from a Java-cloaked app using the antiquated Noir framework to idiomatic Clojure, complete with a MongoDB-to-Postgres migration that's held strong for two years.

Erik frames his insights through cognitive load theory, pioneered by psychologist John Sweller, dissecting how intrinsic challenges—like solving business problems—clash with extraneous distractions, the accidental complexities that drain developers. Early code snippets from 2012 reveal the pitfalls: macros obscuring intent, flexible parameters bewildering linters, and dual atom swaps inviting race conditions. Today, Ardoq's monolith thrives on standard libraries, with Liberator as a stubborn relic, but the real magic lies in ruthless organization. Drawing on "Norris numbers," Erik notes that every order-of-magnitude growth demands strategic shifts—from single-file bliss at 1,000 lines to modular architectures at 200,000. Chesterton's fence looms large here: never refactor without grasping a fence's—er, function's—original purpose, lest you unravel unseen dependencies.

Pet peeves abound in Erik's codebase autopsy. Anonymous functions in reduces whisper "what" but mute "why," forcing readers to dissect implementations rather than converse in domain terms. Higher-order functions, when bespoke, chain cognitive chases across files, unlike trusty core primitives. Deep stacks, laced with parameter mutations and error handling, overload working memory—humans juggle just four to seven items, yet Erik traces 10-hop descents to side-effected depths. His fixes? Name everything, unroll abstractions for orchestration (DRY be damned if it breeds pain), and shallow the stack with macros for repetitive error wrapping. A Unicorn Project stat underscores the irony: only 2.2% of feature time is keyboard time; the rest is process, so Clojure's elegance shines brightest with clean wiring.

Hiring in Clojure's niche? A boon, not a burden. Fewer applicants, but gems from the tight community—tapped via Clojure Slack or conferences—join willingly. Onboarding eases in small teams but demands structure as numbers swell; Erik recounts a recent AI response-chunking exercise, where core.async loops yielded to transducers, slashing test fixtures and illuminating intent. Attrition? Negligible, outpacing industry norms, thanks not just to Clojure but people practices. Erik champions context: developers chat stakeholders directly, owning forks in the road. Autonomy follows, with young engineers driving product sans micromanagement. Ownership reigns—fix problems, even managerial ones—and trust blooms from weekly, agenda-free one-on-ones, nipping issues early.

Ultimately, Erik's tale is one of harmony: sane codebases preserve bandwidth for product prowess, unburdened by JavaScript's gnarls. High-trust, high-context teams accelerate beyond coding, contributing to Ardoq's Thoughtworks radar nod. As applause echoes from Clojure Conj, his message resonates—scale thoughtfully, code readably, lead humanely—to sustain velocity in tech's relentless march.

Like this? Create a free account to export to PDF and ePub, and send to Kindle.

Create a free account