Clojure on Heroku

We're very excited to announce official support for Clojure, going into public beta as of today. Clojure is the third official language supported by Heroku, and is available on the Cedar stack.

Clojure is a Lisp-like functional programming language which runs on the Java Virtual Machine (JVM). It offers powerful concurrency primitives based on immutable data structures, with emphasis on composability and correctness. The Clojure community is vibrant and growing quickly.

More about Clojure in a moment, but first:

Clojure on Heroku in 2 minutes

Create a project with three files:

project.clj

(defproject hello-world "0.0.1"
  :dependencies
    [[org.clojure/clojure "1.2.1"]
     [ring/ring-jetty-adapter "0.3.9"]])

src/demo/web.clj

(ns demo.web
  (:use ring.adapter.jetty))

(defn app [req]
  {:status 200
   :headers {"Content-Type" "text/plain"}
   :body "Hello from Clojure!\n"})

(defn -main []
  (let [port (Integer/parseInt (System/getenv "PORT"))]
    (run-jetty app {:port port})))

Procfile

web: lein run -m demo.web

Commit to Git:

$ git init
$ git add .
$ git commit -m init

Create an app on the Cedar stack and deploy. Your Clojure program and all its dependencies will be built at slug compile time:

$ heroku create --stack cedar
Creating young-earth-944... done, stack is cedar
http://young-earth-944.herokuapp.com/ | git@heroku.com:young-earth-944.git
Git remote heroku added

$ git push heroku master
Counting objects: 7, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (4/4), done.
Writing objects: 100% (7/7), 714 bytes, done.
Total 7 (delta 0), reused 0 (delta 0)

-----> Heroku receiving push
-----> Clojure app detected
-----> Installing Leiningen
       Downloading: leiningen-1.5.2-standalone.jar
       Downloading: rlwrap-0.3.7
       Writing: lein script
-----> Installing dependencies with Leiningen
       Running: lein deps :skip-dev
       Downloading: org/clojure/clojure/1.2.1/clojure-1.2.1.pom from central
       ...
       Copying 11 files to /tmp/build_1cplwgglcalfm/lib
-----> Discovering process types
       Procfile declares types -> web
-----> Compiled slug size is 11.1MB
-----> Launching... done, v2
       http://young-earth-944.herokuapp.com deployed to Heroku

Launch a web process:

$ heroku scale web=1
Scaling web processes... done, now running 1

Then view your app on the web!

$ curl http://young-earth-944.herokuapp.com
Hello from Clojure!

Dev center: Getting Started With Clojure on Heroku/Cedar

Why Clojure?

Clojure combines the expressiveness of Lisp, the agility of a dynamic language, the performance of a compiled language, and the wide applicability of the JVM in a robust, production-ready package. Clojure is a practical language designed to support high-performance, concurrent applications which efficiently interoperate with other software in the JVM ecosystem. All of this combines to make it an ideal tool for the programmer to quickly build robust programs.

Simplicity and Composability

Clojure is known for its simplicity. Simple, in its original sense, means: single-purpose. Functions and language constructs have exactly one purpose, such as atoms for synchronous, independent state change, or protocols for polymorphism (but not any additional behaviour like encapsulation or inheritance). Single-purpose functions and confidence in small pieces of code working well on their own naturally lead to highly composable libraries. This form of simplicity is at the heart of idiomatic Clojure.

Emphasis on Correctness

The simplicity of Clojure makes it easier to "reason about correctness" - that is, look at a piece of code and be able to understand every possible effect it may have. Clojure emphasizes correctness and carefulness, reminiscent of a statically-typed language.

Like all functional programming languages, Clojure enforces being explicit about change and minimizing side-effects. The careful methodology can be seen in Clojure's immutable data structures. If you want to change something, you need to wrap it in an atom, ref, agent or other concurrency primitive. You need to explicitly define what is changeable and how that change is safely managed.

Libraries and Tools

Clojure is a young language, and normally this would mean that it lacks supporting libraries. Clojure's community got a jumpstart by running on the JVM, providing native access to the rich world of Java libraries available.

In addition, the vibrant community of developers working on Clojure has taken things further by developing good tools right from the get-go. Ruby had to wait a long time before getting tools like Gem Bundler, Gemcutter, and RVM; even Rack is fairly recent. In Clojure, equivalent tools like Leiningen, Clojars, and Ring have been there from an early age, allowing Clojure to progress from a well-rounded foundation.

Clojure is very open to incorporating the best ideas from other languages. For example, the core.logic library borrows heavily from Prolog, while Incanter is based on R. The creator of Clojure, Rich Hickey, drew inspiration from a number of other languages, shown nicely on his Clojure bookshelf.

Further Reading: Rationale, from the Clojure official website

Why Clojure on Heroku?

There are three reasons why we chose Clojure as the next available language for the Heroku platform:

  1. New use cases
  2. Clojure's still-evolving community
  3. The Heroku team loves Clojure

1. New Use Cases

Heroku believes in using the right tool for the job. We extend this philosophy to programming languages as well. Software systems have become more complex and powerful, and simultaneously special-purpose tools like Node.js and Clojure become more accessible. These two factors together mean that it increasingly makes sense to choose the programming language for a particular app based on the job at hand.

Ruby, Javascript, and Clojure are all general-purpose languages, but they each excel at certain use cases. Ruby's highly dynamic nature and emphasis on beauty makes it a natural fit for user-facing web apps. Node.js's evented concurrency makes it a great fit for the realtime web. Clojure covers a new use case on the Heroku platform: components which demand correctness, performance, composability; and optionally, access to the Java ecosystem.

Open source / tool examples:

  • Pallet, cloud automation utilizing the JClouds library.
  • Cascalog, a Clojure-based query language for Hadoop.
  • Incanter, a platform for statistical analysis.
  • FleetDB, a NoSQL database.

Companies using Clojure:

  • Relevance is a development shop, Heroku partner, and home to Clojure/core. In addition to their heavy involvement in the Clojure community, they use the language for suitable projects. For example, this client's description of their use of Clojure for a rule-processing engine.
  • FlightCaster, which uses Clojure to interface to Hadoop for machine learning.
  • Pulse is an internal real-time metrics tool for the Heroku platform kernel. It's a distributed, multi-process-type Clojure application that heavily uses several key aspects of Clojure: functional data processing, concurrency, JVM platform and library support. It runs as a Heroku app with no special privileges.
  • Many other companies, ranging from startups like BankSimple to established companies like Akamai, are using Clojure.

These examples show how Clojure support may lead to increased variety of apps deployed the Heroku platform. While it's entirely possible to write a statistical-analysis package in Ruby or a metrics-processing tool in Node.js, Clojure will often be a better fit for these cases and others.

2. Clojure's Still-evolving Community

The Clojure community grew out of the shared goal of developing a modern and forward-looking yet practical and performant programming language. Developers are drawn to Clojure by its elegant design and robust practicality.

Though growing quickly, the Clojure community is small enough to be approachable and accepting of new ideas. This is crucial for a platform like Heroku, which offers a deployment workflow that is a radical departure from that used for server-based deployments. Language communities with heavy investment in traditional deployment methods will be harder to adapt to the Heroku way. Like Node.js, or Ruby in 2009, Clojure's small but fast-growing community means there's an opportunity for the Heroku platform and the Clojure community to work together on evolving the best-practices for Clojure deployment.

3. The Heroku Team Loves Clojure

Heroku has always focused on languages that we ourselves use and love. Ruby was the first, and Javascript/Node.js was the second. Clojure is a language that is rapidly growing in use and esteem on our engineering team.

Mark McGranaghan, lead engineer on Heroku's platform infrastructure, first brought Clojure to Heroku. As the author of Ring (a Rack- or WSGI-like adapter for web apps), he's an active member of the Clojure community and has been a strong voice for our support of Clojure since he joined our team.

We want to deliver a platform that offers an end-to-end developer experience that feels right. "Feels right" is an attribute that can only be judged by developers who use the language in question on a daily basis and belong to that language's community. We use and love Clojure, and that means we can use our own first-hand judgement on the "feels right" attribute of Heroku's Clojure support.

Get Going

Ready to start building Clojure apps on Heroku? Start with these articles in the Heroku Dev Center:

Further reading on Clojure in general:


Special thanks to James Reeves, Phil Hagelberg, and Chris Redinger for alpha-testing Clojure on Heroku and contributing to this post.

Browse the blog archives or subscribe to the full-text feed.