Clojure is a dynamic, general-purpose, functional programming language and a modern dialect of Lisp. Created by Rich Hickey and first released on October 16, 2007, Clojure runs primarily on the Java Virtual Machine (JVM), with parallel runtimes targeting JavaScript (ClojureScript) and the .NET Common Language Runtime (ClojureCLR) [1][2]. The language emphasizes immutable persistent data structures, first-class functions, software transactional memory (STM), and concurrency primitives designed to make managing shared state explicit and safer than the lock-based concurrency typical of mainstream object-oriented languages [3].
Clojure was designed as a practical Lisp for working programmers, hosted on an industrial runtime so Java libraries and tooling can be reused directly. The language has a small core, treats data as values, and encourages programs built from small composable functions operating on a handful of generic data structures: lists, vectors, maps, and sets. Its emphasis on immutability has influenced other languages and libraries, including Scala collections and state management in the React ecosystem [4]. Notable users include Nubank, Walmart, Citibank, Apple, Atlassian, Salesforce, CircleCI, SoundCloud, and Metabase.
Rich Hickey began work on Clojure in 2005 while he was a self-employed contract programmer in New York City. He had been writing software for over twenty years, mostly in C++, Java, and Common Lisp, and had grown frustrated with the difficulty of writing correct concurrent programs in object-oriented languages. He took a self-funded sabbatical of roughly two and a half years to design a new language combining three goals at once: a Lisp, with strong support for functional programming, running on a popular industrial platform [6].
Hickey released Clojure publicly on October 16, 2007, by posting an announcement to the comp.lang.lisp newsgroup and launching the clojure.org website. Within months an active community had formed around the clojure mailing list and the #clojure IRC channel [7].
Hickey wrote a now widely cited "Rationale" document explaining the project's goals. He wanted Clojure to be a Lisp without the historical baggage of Common Lisp or the academic minimalism of Scheme and Racket; a language for functional programming with immutability as the default; a hosted language that leveraged the Java ecosystem; and concurrency designed into the language rather than bolted on. These four pillars (Lisp, functional, hosted, concurrent) have remained the core design philosophy ever since [8].
Clojure 1.0 was released on May 4, 2009, marking the first version with stable APIs and an officially blessed contributor process. The release of Programming Clojure by Stuart Halloway later in 2009 helped accelerate adoption beyond the early adopter pool [9].
Clojure is a Lisp, which means programs are written as data: source code consists of nested lists and other literal data structures read and evaluated by the same machinery the program uses at runtime. This property, called homoiconicity, is the foundation of Clojure's macro system.
The core data structures are immutable and persistent. When you "modify" a vector or map in Clojure, you do not mutate the original; you receive a new structure that shares most of its memory with the previous version through structural sharing. The implementation is based on Hash Array Mapped Tries (HAMTs), a technique published by Phil Bagwell in 2001 that gives near constant time lookup, insertion, and update for very large collections [10].
The language has a compact but powerful set of core features:
A small example illustrates the syntax and the data orientation:
(defn word-frequencies [text]
(->> text
(re-seq #"\w+")
(map clojure.string/lower-case)
frequencies
(sort-by val >)
(take 10)))
The ->> threading macro pipes a value through a series of expressions, reading top to bottom and avoiding deeply nested calls. Functions like frequencies, sort-by, and take all return immutable collections, never mutating their inputs.
Clojure programs are typically developed at a REPL. A running Clojure process accepts new code at any time, recompiles individual functions, and inspects live program state. Most Clojure developers connect their editor directly to a running REPL inside the application they are building, evaluating expressions in place rather than restarting the program.
Clojure's most distinctive contribution to language design is its treatment of identity, state, and time as separate concepts. Hickey argued in his 2009 talk "Are We There Yet?" that conflating identity with state in object-oriented programming is the root cause of most concurrency bugs. In Clojure, an immutable value is what you observe; an identity is a name pointing to a succession of values over time; and the language provides four reference types that bind names to values under different concurrency policies [11].
| Reference type | Coordination | Synchrony | Typical use |
|---|---|---|---|
| Var | None (per-thread) | Synchronous | Dynamic binding, configuration, per-request context |
| Atom | Uncoordinated | Synchronous | Independent counters, caches, single-cell state |
| Ref | Coordinated (STM) | Synchronous | Transfers between accounts, multi-cell invariants |
| Agent | Uncoordinated | Asynchronous | Background work, decoupled updates |
Refs use a multi-version concurrency control STM modeled on database transactions. Inside a dosync block, reads see a consistent snapshot and writes either commit atomically or retry on conflict. Atoms use compare-and-swap on a single cell. Agents queue updates and apply them in the background.
In 2013 the core.async library introduced a fifth model: Communicating Sequential Processes, modeled on Tony Hoare's 1978 CSP paper and on Go's goroutines. Channels are first-class values; the go macro rewrites blocking channel operations into a state machine that runs on a small thread pool [12].
Reducers (Clojure 1.5, 2013) and transducers (Clojure 1.7, 2014) extend the model further. Transducers are composable algorithmic transformations decoupled from the input or output collection; the same transformation can apply to a vector, a lazy sequence, a channel, or an observable stream [13]. Clojure does not natively implement the actor model in the Erlang sense; agents share some surface similarities but lack mailboxes and supervision trees.
ClojureScript is a compiler that targets JavaScript instead of JVM bytecode. Hickey announced ClojureScript at Strange Loop in St. Louis on July 20, 2011. The compiler emits JavaScript that is then minified by the Google Closure Compiler, taking advantage of Closure's whole-program optimizations to produce small, dead-code-eliminated bundles [14].
ClojureScript is a near-complete subset of Clojure. Persistent data structures, lazy sequences, macros, multimethods, protocols, and core.async all work the same way. The main differences come from the host platform: there is no STM (because the JavaScript runtime is single-threaded), no agents, no first-class threads, and macros must be defined in Clojure files because compilation and runtime are separated.
The ClojureScript front-end ecosystem is dominated by Reagent and re-frame, a thin idiomatic wrapper around React combined with a Redux-like state management framework that predates Redux. Earlier libraries like Om by David Nolen demonstrated immutable data structures plus React-style virtual DOM rendering and inspired several non-Clojure libraries. The shadow-cljs build tool by Thomas Heller has become the standard for ClojureScript projects, offering hot module reload and npm integration. Production users of ClojureScript include CircleCI's web UI, Pitch.com's collaborative slide editor, Roam Research's outliner, and large parts of Nubank's customer-facing tooling.
Besides ClojureScript, several other Clojure runtimes target additional platforms:
For most of Clojure's first decade the dominant build tool was Leiningen ("lein"), created by Phil Hagelberg in 2009. Leiningen wraps Maven underneath but provides a Clojure-flavored project.clj file, plugins, and a friendly command-line interface [16]. Boot, an alternative tool by Micha Niskin and Alan Dipert, briefly competed with Leiningen by treating the build itself as a Clojure program of pipeline filters.
In 2018 the Clojure core team released the official Clojure CLI tools and the deps.edn file format, providing a minimal, library-oriented dependency resolver and a clean separation between dependency management and build automation. Most new Clojure projects since 2020 default to deps.edn, with companion tools such as tools.build or Polylith handling build steps.
Dependency artifacts are published on Maven Central or on Clojars, a community-run Maven-compatible repository hosting tens of thousands of Clojure libraries. Editor support is mature: the canonical Emacs experience is CIDER, VS Code users rely on Calva, and IntelliJ users rely on Cursive, a dedicated Clojure plugin for IntelliJ IDEA by Colin Fleming. All three integrate with nREPL, the standard network REPL protocol.
The Clojure ecosystem favors small composable libraries over heavyweight frameworks. A typical web service might combine four or five independent libraries rather than adopt a single framework.
Web servers and HTTP. Ring is the underlying abstraction: a request is a Clojure map, a response is a Clojure map, and middleware is a function wrapping a handler. Compojure layers a routing DSL on top. Pedestal is Cognitect's interceptor-based framework with first-class async support. Reitit is a newer data-driven router. Aleph and http-kit provide non-blocking servers built on Netty.
HTML and frontend. Hiccup represents HTML as Clojure vectors, a style copied widely outside Clojure. Reagent and re-frame dominate ClojureScript SPAs.
Data and databases. next.jdbc is the modern JDBC wrapper. HoneySQL builds SQL from Clojure data. Datomic is Cognitect's immutable temporal database, designed around an EAV data model and a Datalog query language. Datascript is an in-memory port of Datomic's API for browser use. XTDB (formerly Crux) is an open-source bitemporal database in Clojure.
Concurrency and core extensions. core.async (CSP channels), core.logic (a port of miniKanren for logic programming), core.match (pattern matching), and core.cache.
Validation. clojure.spec is the official specification library introduced in Clojure 1.9 (2017), used for runtime validation, generative testing, and documentation. Malli is a popular alternative. Plumatic Schema predates spec and is still in wide use. Specter offers a tiny algebra for navigating deeply nested structures. Neanderthal wraps native BLAS/LAPACK and CUDA for high-performance linear algebra.
Cognitect was the steward of Clojure for most of its existence. The company was formed in 2013 from the merger of Relevance Inc. (the consultancy founded by Stuart Halloway and Justin Gehtland in 2003) and Metadata Partners (Hickey's vehicle for funding Clojure work). Cognitect employed several of Clojure's most active maintainers, including Hickey, Halloway, Alex Miller, and Stuart Sierra. It released several flagship products: Datomic (2012), Pedestal (2013), and Transit, a JSON-friendly serialization format introduced in 2014 (see transit format) [17].
Nubank, the Brazilian fintech founded in 2013, was already the largest Clojure shop in the world by the late 2010s, running thousands of microservices on Datomic and Kafka. On July 8, 2020, Nubank announced it had acquired Cognitect, bringing the entire core team and Datomic in-house [5]. The Clojure language itself remained openly developed and Apache 2.0 licensed. In April 2022, Hickey announced his retirement from Nubank and from active language development, handing stewardship to Alex Miller.
Clojure's industrial footprint is concentrated in domains where correctness and concurrency matter: banking, fintech, e-commerce, developer tooling, and analytics.
The annual State of Clojure survey consistently finds web development, data engineering, and back-end services as the dominant use cases [19].
Clojure has a smaller AI and machine learning community than Python and is rarely chosen as a primary numerics platform. The JVM is well suited to data engineering and inference at scale but lacks the breadth of ML libraries that NumPy, PyTorch, and TensorFlow have built up around Python.
Notable projects include:
In practice, the most common pattern in 2024-2025 is to use Clojure as the orchestration and tooling layer (for routing, prompt construction, evaluation harnesses, agent loops, and ETL) while delegating heavy model training and inference to Python services or GPU servers reached over HTTP.
The flagship event is Clojure/conj, an annual US conference held since 2010, organized originally by Cognitect and since 2020 by community-led groups. EuroClojure has run in various European cities since 2012. Earlier regional conferences (Clojure/west, Clojure/north) came and went as the community shifted toward virtual events. re:Clojure is a community-run virtual conference held since 2020 [20].
Strange Loop, the multi-paradigm conference held in St. Louis from 2010 to 2023, was not Clojure-specific but became closely associated with the language because Hickey delivered several of his most influential talks there.
The State of Clojure annual survey gathers thousands of responses on tooling and developer happiness. The Clojurians Slack workspace (roughly 30,000 members) is the primary chat venue. ClojureBridge, launched in 2014, is a global volunteer initiative running free workshops aimed at increasing the participation of underrepresented groups in the community.
Rich Hickey's conference talks are among the most widely watched in software engineering, regularly appearing on "best of" lists outside the Clojure community [21]. Selected talks include:
The Clojure team practices what Hickey calls "slow growth on a stable base" and has avoided breaking changes wherever possible. Programs written for Clojure 1.0 in 2009 generally still compile and run on the latest version with no modification.
| Version | Release date | Highlights |
|---|---|---|
| 1.0 | May 4, 2009 | First stable release; persistent collections, STM, agents, Java interop |
| 1.1 | December 31, 2009 | Futures, promises, chunked sequences |
| 1.2 | August 19, 2010 | Protocols, deftype, defrecord, Maven artifacts |
| 1.3 | September 23, 2011 | Primitive arithmetic, contrib library split |
| 1.4 | April 15, 2012 | Reader literals, EDN, mapv/filterv |
| 1.5 | March 1, 2013 | Reducers, faster persistent collections |
| 1.6 | March 25, 2014 | Java 8 support, hashing changes |
| 1.7 | June 30, 2015 | Transducers, reader conditionals |
| 1.8 | January 19, 2016 | Direct linking, socket REPL, string functions |
| 1.9 | December 8, 2017 | clojure.spec, CLI tools and deps.edn |
| 1.10 | December 17, 2018 | Improved error messages, prepl, Java 11 support |
| 1.11 | March 22, 2022 | Native keyword args, parse-long/parse-double |
| 1.12 | September 5, 2024 | Method values, qualified methods, array class syntax |
Releases since 1.10 have been bug-fix dominant with carefully scoped feature additions, reflecting the project's preference for backward compatibility over fashion-driven changes [22].
Strengths.
Trade-offs.
In the experience of teams who use the language at scale, these trade-offs are vastly outweighed by the long-term maintainability benefits of immutability, REPL-driven development, and a stable language [5][19].