# How Dependencies Are Configured in the TeslaMate Supervisor Tree

> Discover how TeslaMate configures dependencies within its supervisor tree. Learn about OTP supervisors, restart strategies, and dynamic child specifications for efficient process management.

- Repository: [TeslaMate/teslamate](https://github.com/teslamate-org/teslamate)
- Tags: internals
- Published: 2026-06-16

---

**TeslaMate configures its runtime process hierarchy through a single OTP supervisor in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex) that uses the `:one_for_one` restart strategy, dynamically assembling child specifications based on environment settings for MQTT and import directories.**

TeslaMate, the open-source self-hosted data logger for Tesla vehicles, relies on a robust Erlang/OTP supervision tree to manage its concurrent processes. The foundation of this architecture lies in how dependencies are configured in the TeslaMate supervisor tree, specifically within the application startup sequence. By leveraging Elixir's Supervisor behaviour, TeslaMate ensures that critical components like database connections, API clients, and background workers restart independently when failures occur.

## The Root Supervisor Architecture

The entry point for the supervision tree is `TeslaMate.Application.start/2`, defined in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex). This function initializes the entire runtime by starting a supervisor with the **`:one_for_one`** strategy:

```elixir

# lib/teslamate/application.ex

def start(_type, _args) do
  # …

  Supervisor.start_link(children(), strategy: :one_for_one, name: TeslaMate.Supervisor)
end

```

The `:one_for_one` strategy ensures that if a single child process crashes, only that specific process is restarted, leaving the rest of the system unaffected. This design provides fault isolation between distinct functional areas like database access and vehicle communication.

## Dynamic Child Specification in children/0

The `children/0` function serves as the dependency manifest, returning a list of child specifications that varies based on runtime configuration. The function checks two environment keys:

- `Application.get_env(:teslamate, :import_directory)` – Determines if the system should run in import mode
- `Application.get_env(:teslamate, :mqtt)` – Controls whether the MQTT bridge starts

Each entry in the returned list follows Elixir's child specification format, either as a module name (for simple `start_link` functions) or as a tuple `{module, opts}` for processes requiring specific initialization arguments.

## Normal Mode Configuration

When operating in standard mode (no import directory configured), `children/0` returns the following list:

```elixir
[
  TeslaMate.Repo,
  TeslaMate.Vault,
  TeslaMate.HTTP,
  TeslaMate.Api,
  TeslaMate.Updater,
  {Phoenix.PubSub, name: TeslaMate.PubSub},
  TeslaMateWeb.Endpoint,
  TeslaMate.Terrain,
  TeslaMate.Vehicles,
  if(mqtt_config != nil, do: {TeslaMate.Mqtt, mqtt_config}),
  TeslaMate.Repair
]
|> Enum.reject(&is_nil/1)

```

The `Enum.reject(&is_nil/1)` filter at the end removes the optional MQTT child when the configuration is absent, ensuring the supervisor only starts configured dependencies.

The responsibilities of these core processes include:

- **`TeslaMate.Repo`** – Manages the Ecto database connection pool
- **`TeslaMate.Vault`** – Handles encrypted storage of API tokens using Cloak
- **`TeslaMate.HTTP`** – Provides a thin wrapper around the Tesla HTTP client for outbound requests
- **`TeslaMate.Api`** – Implements the high-level Tesla API client for vehicle communication
- **`TeslaMate.Updater`** – Manages firmware update tracking and data migrations
- **`Phoenix.PubSub`** – Enables the Pub/Sub backbone for LiveView real-time updates
- **`TeslaMateWeb.Endpoint`** – Starts the Phoenix HTTP server
- **`TeslaMate.Terrain`** – Provides SRTM elevation data lookups
- **`TeslaMate.Vehicles`** – Supervises individual vehicle process instances
- **`TeslaMate.Repair`** – Runs background repair and maintenance tasks

## Import Mode Configuration

When `Application.get_env(:teslamate, :import_directory)` returns a path, the supervision tree switches to import mode with a modified dependency list:

```elixir
[
  TeslaMate.Repo,
  TeslaMate.Vault,
  TeslaMate.HTTP,
  TeslaMate.Api,
  TeslaMate.Updater,
  {Phoenix.PubSub, name: TeslaMate.PubSub},
  TeslaMateWeb.Endpoint,
  {TeslaMate.Terrain, disabled: true},
  {TeslaMate.Repair, limit: 250},
  {TeslaMate.Import, directory: import_directory}
]

```

Key differences from normal mode include:

- **`TeslaMate.Terrain`** starts with `disabled: true` to skip elevation lookups during bulk imports
- **`TeslaMate.Repair`** receives a `limit: 250` option to throttle background work
- **`TeslaMate.Import`** is added to process CSV files from the specified directory

## Optional MQTT Integration

The MQTT dependency demonstrates conditional supervision. Rather than using a static list, the configuration evaluates at runtime:

```elixir
if(mqtt_config != nil, do: {TeslaMate.Mqtt, mqtt_config})

```

When the `:mqtt` key exists in the application environment, the tuple `{TeslaMate.Mqtt, mqtt_config}` enters the children list. Otherwise, the expression returns `nil`, and `Enum.reject(&is_nil/1)` filters it out before the supervisor starts. This pattern allows the same codebase to support both MQTT-enabled and MQTT-disabled deployments without code changes.

## Extending the Supervision Tree

To add a new dependency, such as a telemetry collector, you must modify the `children/0` function in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex). For example, adding a `TeslaMate.Telemetry` GenServer:

```elixir

# Inside lib/teslamate/application.ex → children/0

[
  # … existing children …

  TeslaMate.Vehicles,
  TeslaMate.Telemetry,      # ← new child

  if(mqtt_config != nil, do: {TeslaMate.Mqtt, mqtt_config}),
  TeslaMate.Repair
]
|> Enum.reject(&is_nil/1)

```

Because the supervisor uses `:one_for_one`, the new telemetry process starts automatically during application boot and restarts independently if it crashes.

## Summary

- **TeslaMate** uses a single supervisor in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex) with the **`:one_for_one`** restart strategy to manage all runtime dependencies.
- The **`children/0`** function dynamically builds the child specification list based on environment variables `:import_directory` and `:mqtt`.
- **Normal mode** starts eleven core processes including database connections, API clients, and background workers.
- **Import mode** modifies the tree to disable terrain lookups, throttle repairs, and add the CSV import processor.
- Optional dependencies use runtime conditionals with `Enum.reject(&is_nil/1)` to filter unconfigured processes.
- Configuration originates in [`config/config.exs`](https://github.com/teslamate-org/teslamate/blob/main/config/config.exs) and environment-specific files (dev, prod, test).

## Frequently Asked Questions

### What restart strategy does TeslaMate use for its supervisor tree?

TeslaMate uses the **`:one_for_one`** strategy, implemented in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex). This means if a single child process fails, the supervisor restarts only that specific process while leaving all other sibling processes running. This provides fault isolation between the database pool, API clients, and web interface.

### How do I disable the MQTT dependency in TeslaMate?

Remove the `:mqtt` configuration from your [`config/config.exs`](https://github.com/teslamate-org/teslamate/blob/main/config/config.exs) or environment-specific config file. When `Application.get_env(:teslamate, :mqtt)` returns `nil`, the `children/0` function in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex) passes `nil` to the MQTT slot, and `Enum.reject(&is_nil/1)` filters it out before the supervisor starts. No code changes are required.

### What happens when an import directory is configured in TeslaMate?

When the `:import_directory` environment variable is set, TeslaMate switches to import mode. The `children/0` function returns a modified list that starts `TeslaMate.Terrain` with `disabled: true`, limits `TeslaMate.Repair` to 250 concurrent tasks, and adds `TeslaMate.Import` to process CSV files from the specified directory. This optimizes the supervision tree for bulk data ingestion rather than real-time vehicle monitoring.

### Where does TeslaMate read its supervision configuration from?

TeslaMate reads configuration from the application environment, specifically the `Application.get_env/2` calls in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex). The relevant keys (`:mqtt` and `:import_directory`) are defined in [`config/config.exs`](https://github.com/teslamate-org/teslamate/blob/main/config/config.exs) and can be overridden in environment-specific files like [`config/prod.exs`](https://github.com/teslamate-org/teslamate/blob/main/config/prod.exs) or [`config/dev.exs`](https://github.com/teslamate-org/teslamate/blob/main/config/dev.exs). The supervisor tree builds dynamically at runtime based on these values.