How OTP Applications are structured
Tags: elixir, beginners, programming, erlang
Published: 2018-09-18 14:21:31

---
title: How OTP Applications are structured
layout: layout_elixir_alchemy
description: OTP uses applications to package code into units or components. In this edition of Elixir Alchemy, we'll learn about how Elixir applications are used, configured and compiled.
cover_image: https://blog.appsignal.com/images/blog/2018-09/ea-otp.jpg
tags: elixir, beginners, programming, erlang
published: true
canonical_url: https://blog.appsignal.com/2018/09/18/elixir-alchemy-how-otp-applications-are-structured.html
---

[OTP](https://github.com/erlang/otp), the framework that provides standards to help build Erlang applications, uses *applications* to package code into units or components. This convention helps structuring your code into logical groups of modules and a way to start and stop the application's supervisors. Your Phoenix project is an application, but the Phoenix framework and Ecto are applications too.

An application is a component that can be compiled by itself. It can depend on other applications, and it can take its own configuration. Unlike in other languages, this convention provides a standardized way to specify how the VM should interact with it.

Aside from the compiled `.beam` files containing virtual machine code, compiled applications consist of an *application specification* `.app` file that tells the VM how to handle the application, and an optional *application callback module* that is used to start, run and stop the application.

## Application Callback Modules

For applications with supervisors, the application callback module defines functions that start and stop the application. Applications without supervisors (usually libraries with functions you can call without no internal state) omit the callback module since the application doesn't need to be started.

In Elixir, an application callback module uses [the `Application` behavior](https://hexdocs.pm/elixir/Application.html). The behavior implements the `start/2` and `stop/1` callbacks. The former starts the application's main supervisor, and the latter is an optional callback that's used to clean up after stopping the supervisor.

Elixir's `mix new` task automatically creates an application callback module when a new project is generated with the `--sup` flag.

```sh
$ mix new --sup elixir_app
```

The generated project contains an application callback module in `lib/elixir_app/application.ex`.

``` elixir
defmodule ElixirApp.Application do
  # See https://hexdocs.pm/elixir/Application.html
  # for more information on OTP Applications
  @moduledoc false

  use Application

  def start(_type, _args) do
    # List all child processes to be supervised
    children = [
      # Starts a worker by calling: ElixirApp.Worker.start_link(arg)
      # {ElixirApp.Worker, arg},
    ]

    # See https://hexdocs.pm/elixir/Supervisor.html
    # for other strategies and supported options
    opts = [strategy: :one_for_one, name: ElixirApp.Supervisor]
    Supervisor.start_link(children, opts)
  end
end
```

When used, the `Application` module adds a [stub of the `stop/1` function](https://github.com/elixir-lang/elixir/blob/0429cdd95f10abe2f5b3d188c2c3574132cae474/lib/elixir/lib/application.ex#L328-L330), which returns an ok-tuple. The generated `start/2` function starts the app's main supervisor.

## Application Specifications

Running `mix compile.app` places the application's specification in the `.app` file in the `ebin` directory, and is one of the steps taken when compiling the app with `mix compile`.

The specification contains Erlang terms which define the application. It lists the modules defined in the app, the version number and a list of other apps that the app depends on. It also specifies the module to be used as the callback that starts the app.

The specification file is based on the settings in the application’s `mix.exs` file. To be able to generate the specification, each app must have a name and version number defined in its project function.

``` elixir
defmodule ElixirApp.MixProject do
  use Mix.Project

  def project do
    [
      app: :elixir_app,
      version: "0.1.0"
    ]
  end
end
```

Below is a minimal sample `mix.exs` file, which only lists the project name and version number, yields a specification that lists Elixir’s default applications and specifies the modules in the app.

``` erlang
{application,elixir_app,
             [{applications,[kernel,stdlib,elixir]},
              {description,"elixir_app"},
              {modules,['Elixir.ElixirApp','Elixir.ElixirApp.Application']},
              {registered,[]},
              {vsn,"0.1.0"}]}.
```

### Specifying and Configuring the Application Callback Module

Aside from the app's name and version number, a `mix.exs` file generated with the `--sup` option has an `application` function with a `mod` key.

``` elixir
defmodule ElixirApp.MixProject do
  # ...

  def application do
    [
      mod: {ElixirApp.Application, []}
    ]
  end
end
```

When generating the specification, it includes the callback module. This key points to the application's callback module, so the VM knows which module to use to start the application.

``` erlang
{application,elixir_app,
             [{applications,[kernel,stdlib,elixir,logger]},
              {description,"elixir_app"},
              {modules,['Elixir.ElixirApp','Elixir.ElixirApp.Application']},
              {registered,[]},
              {vsn,"0.1.0"},
              {mod,{'Elixir.ElixirApp.Application',[]}}]}.
```

*Tip*: The list in the `:mod`-tuple is used to pass configuration options to the application. Anything passed in ends up as the arguments to the callback module's `start/2` function.

### `:applications` and `:extra_applications`

The `applications` key in the specification lists all the applications that your app depends on. By default, `mix compile.app` includes `kernel` `stdlib` and `elixir`.

``` elixir
defmodule ElixirApp.MixProject do
  use Mix.Project

  def project do
    [
      app: :elixir_app,
      version: "0.1.0",
      deps: [{:appsignal, "~> 1.0.0"}]
    ]
  end
end
```

Dependencies are automatically added to the `applications` list, and they’re automatically started before the application boots if they have an Application module.

``` erlang
{application,elixir_app,
             [{applications,[kernel,stdlib,elixir,appsignal]},
              {description,"elixir_app"},
              {modules,['Elixir.ElixirApp','Elixir.ElixirApp.Application']},
              {registered,[]},
              {vsn,"0.1.0"}]}.
```

To add more applications like Elixir’s `logger`, you add them to the `:extra_applications` key and they will subsequently be added to the existing list.

``` elixir
defmodule ElixirApp.MixProject do

  # ...

  def application do
    [
      extra_applications: [:logger],
      mod: {ElixirApp.Application, []}
    ]
  end
end
```

The `:applications` key is used to explicitly specify the applications that are to be included in the specification. When used, only the listed applications and the defaults will be added. Any other dependencies are not automatically included.

## Applications all the way down

Each seperate library, as well as your application itself, is an application. Some applications have a supervision tree, requiring them to have a callback module that takes care of starting and stopping the whole application.

Your application can depend on other applications, and each of these can have their own supervision trees and callback modules. Whatever's in there, it's always specified in the application specification file. Think of it as the formula for your Elixir. 😉

This concludes our overview of OTP applications in Elixir. We've tried convey some of the beauty of one of OTP's conventions. It is one of the many things we love about Elixir. If you do too, let us know what you'd like to see us write about in a comment, or subscribe to the [Elixir Alchemy newsletter](https://appsignal.com/elixir-alchemy).