Heroku is a cloud platform as a service supporting several programming languages. One of the first cloud platforms, Heroku has been in development since June 2007, when it supported only the Ruby programming language, but now supports Java, Node.js, Scala, Clojure, Python, PHP, and Go
How Heroku Works
This is a high-level, technical description of how Heroku works. It ties together many of the concepts you’ll encounter while writing, configuring, deploying and running applications on the Heroku platform.
Performing one of the Getting Started tutorials will make the concepts in this documentation more concrete.
Read this document sequentially: in order to tell a coherent story, it incrementally unveils and refines the concepts describing the platform.
The final section ties all the definitions together, providing a deploy-time and runtime-view of Heroku.
Defining an application
Heroku lets you deploy, run and manage applications written in Ruby, Node.js, Java, Python, Clojure, Scala, Go and PHP.
An application is a collection of source code written in one of these languages, perhaps a framework, and some dependency description that instructs a build system as to which additional dependencies are needed in order to build and run the application.
Terminology (Preliminary): Applications consist of your source code and a description of any dependencies.
Dependency mechanisms vary across languages: in Ruby you use a Gemfile
, in Python a requirements.txt
, in Node.js a package.json
, in Java a pom.xml
and so on.
The source code for your application, together with the dependency file, should provide enough information for the Heroku platform to build your application, to produce something that can be executed.
Knowing what to execute
You don’t need to make many changes to an application in order to run it on Heroku. One requirement is informing the platform as to which parts of your application are runnable.
If you’re using some established framework, Heroku can figure it out. For example, in Ruby on Rails, it’s typically rails server
, in Django it’s python <app>/manage.py runserver
and in Node.js it’s the main
field in package.json
.
Terminology: Procfiles list process types – named commands that you may want executed.
For other applications, you may need to explicitly declare what can be executed. You do this in a text file that accompanies your source code – a Procfile. Each line declares a process type – a named command that can be executed against your built application. For example, your Procfile may look like this:
web: java -jar lib/foobar.jar $PORT
queue: java -jar lib/queue-processor.jar
This file declares a web
process type and provides the command that needs to be executed in order to run it (in this case, java -jar lib/foobar.jar $PORT
). It also declares a queue
process type, and its corresponding command.
The earlier definition of an application can now be refined to include this single additional Procfile.
Terminology: Applications consist of your source code, a description of any dependencies, and a Procfile.
Heroku is a polyglot platform – it lets you build, run and scale applications in a similar manner across all the languages – utilizing the dependencies and Procfile. The Procfile exposes an architectural aspect of your application (in the above example there are two entry points to the application) and this architecture lets you, for example, scale each part independently. An excellent guide to architecture principles that work well for applications running on Heroku can be found in Architecting Applications for Heroku.
Deploying applications
Git is a powerful, distributed version control system that many developers use to manage and version source code. The Heroku platform uses Git as the primary means for deploying applications (there are other ways to transport your source code to Heroku, including via an API).
When you create an application on Heroku, it associates a new Git remote, typically named heroku
, with the local Git repository for your application.
As a result, deploying code is just the familiar git push
, but to the heroku
remote instead:
git push heroku master
Terminology: Deploying applications involves sending the application to Heroku using either Git, GitHub, or via an API.
There are many other ways of deploying applications too. For example, you can enable GitHub integration so that each new pull request is associated with its own new application, which enables all sorts of continuous integration scenarios. Or you can use the Heroku API to build and release apps.
Deployment then, is about moving your application from your local system to Heroku – and Heroku provides several ways in which apps can be deployed.
Building applications
When the Heroku platform receives the application source, it initiates a build of the source application. The build mechanism is typically language specific, but follows the same pattern, typically retrieving the specified dependencies, and creating any necessary assets (whether as simple as processing style sheets or as complex as compiling code).
Advanced: Buildpacks lie behind the slug compilation process. Buildpacks take your application, its dependencies, and the language runtime, and produce slugs. They’re open source – enabling you to extend Heroku to other languages and frameworks.
For example, when the build system receives a Rails application, it may fetch all the dependencies specified in the Gemfile, as well as generate files based on the asset pipeline. A Java application may fetch binary library dependencies using Maven, compile the source code together with those libraries, and produce a JAR file to execute.
The source code for your application, together with the fetched dependencies and output of the build phase such as generated assets or compiled code, as well as the language and framework, are assembled into a slug.
Terminology: A slug is a bundle of your source, fetched dependencies, the language runtime, and compiled/generated output of the build system – ready for execution.
These slugs are a fundamental aspect of what happens during application execution – they contain your compiled, assembled application – ready to run – together with the instructions (the Procfile) of what you may want to execute.
Running applications on dynos
Heroku executes applications by running a command you specified in the Procfile, on a dyno that’s been preloaded with your prepared slug (in fact, with your release, which extends your slug and a few items not yet defined: config vars and add-ons).
Think of a running dyno as a lightweight, secure, virtualized Unix container that contains your application slug in its file system.
Terminology: Dynos are isolated, virtualized Unix containers, that provide the environment required to run an application.
Generally, if you deploy an application for the first time, Heroku will run 1 web dyno automatically. In other words, it will boot a dyno, load it with your slug, and execute the command you’ve associated with the web process type in your Procfile.
You have control over how many dynos are running at any given time. Given the Procfile example earlier, you can start 5 dynos, 3 for the web and 2 for the queue process types, as follows:
heroku ps:scale web=3 queue=2
When you deploy a new version of an application, all of the currently executing dynos are killed, and new ones (with the new release) are started to replace them – preserving the existing dyno formation.
Terminology: Your application’s dyno formation is the total number of currently-executing dynos, divided between the various process types you have scaled.
To understand what’s executing, you just need to know what dynos are running which process types:
heroku ps
== web: 'java lib/foobar.jar $PORT'
web.1: up 2013/02/07 18:59:17 (~ 13m ago)
web.2: up 2013/02/07 18:52:08 (~ 20m ago)
web.3: up 2013/02/07 18:31:14 (~ 41m ago)
== queue: `java lib/queue-processor.jar`
queue.1: up 2013/02/07 18:40:48 (~ 32m ago)
queue.2: up 2013/02/07 18:40:48 (~ 32m ago)
Dynos then, are an important means of scaling your application. In this example, the application is well architected to allow for the independent scaling of web and queue worker dynos.
Config vars
An application’s configuration is everything that is likely to vary between environments (staging, production, developer environments, etc.). This includes backing services such as databases, credentials, or environment variables that provide some specific information to your application.
Heroku lets you run your application with a customizable configuration – the configuration sits outside of your application code and can be changed independently of it.
The configuration for an application is stored in config vars. For example, here’s how to configure an encryption key for an application:
heroku config:set ENCRYPTION_KEY=my_secret_launch_codes
Adding config vars and restarting demoapp... done, v14
ENCRYPTION_KEY: my_secret_launch_codes
Terminology: Config vars contain customizable configuration data that can be changed independently of your source code. The configuration is exposed to a running application via environment variables.
At runtime, all of the config vars are exposed as environment variables – so they can be easily extracted programmatically. A Ruby application deployed with the above config var can access it by calling ENV["ENCRYPTION_KEY"]
.
All dynos in an application will have access to the exact same set of config vars at runtime.