# How TeslaMate Uses GenServer and Supervisor Patterns for Vehicle Management

> Discover how TeslaMate leverages GenServer and Supervisor patterns for robust vehicle management. Learn how its fault-tolerant design ensures reliable fleet operations and isolates vehicle processes.

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

---

**TeslaMate models each physical Tesla vehicle as a separate GenStateMachine process supervised by a dynamic Supervisor, ensuring fault-tolerant fleet management where a crash in one vehicle process does not affect others.**

TeslaMate is a self-hosted data logger for Tesla vehicles built with Elixir. According to the teslamate-org/teslamate source code, the application leverages Erlang/OTP's **GenServer** and **Supervisor** patterns to isolate each vehicle into its own managed process, creating a resilient architecture that scales from a single car to an entire fleet without code changes.

## Supervisor Architecture with TeslaMate.Vehicles

The `TeslaMate.Vehicles` module acts as the central supervisor for all vehicle processes. Defined in [`lib/teslamate/vehicles.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles.ex), it `use Supervisor` to implement a dynamic supervision tree that manages the lifecycle of every vehicle in the fleet.

### Application Startup and Initialization

The application boot sequence begins in [`lib/teslamate/application.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/application.ex), where the root supervisor starts `TeslaMate.Vehicles` via `Supervisor.start_link/3`. During initialization, the `init/1` callback queries the Tesla API to retrieve the vehicle list, then builds a child specification for each car using `TeslaMate.Vehicles.Vehicle.child_spec/1`. This creates a uniquely-named process for each vehicle under the supervisor's control.

### Fault Isolation with One-for-One Strategy

The supervisor employs a `:one_for_one` restart strategy. If a single vehicle process crashes—perhaps due to a malformed API response or network timeout—only that specific process is restarted. This isolation ensures that a fault in one vehicle's data stream never interrupts logging for other vehicles in the fleet.

### Runtime Fleet Control

Helper functions in [`lib/teslamate/vehicles.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles.ex) provide operational control over the entire fleet:

- `kill/0` terminates all vehicle processes using `Supervisor.stop/2`
- `restart/0` triggers a complete supervisor restart
- `list/0` returns active children via `Supervisor.which_children/1`

## Vehicle Processes as State Machines

Each vehicle runs as an independent process managed by `TeslaMate.Vehicles.Vehicle`, which uses `GenStateMachine` (a GenServer extension) to model complex vehicle states and transitions.

### Process Registration and Naming

In [`lib/teslamate/vehicles/vehicle.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles/vehicle.ex), the `start_link/1` function creates a uniquely named process for each car using an atom derived from the vehicle ID: `:"#{car.id}"`. This global registration allows other processes to send messages to specific vehicles without maintaining PID references.

### State Machine Implementation

The `handle_event/4` callback implements a finite state machine with distinct states including `:start`, `:online`, `:asleep`, `:offline`, `:driving`, `:charging`, `:suspended`, and `:updating`. Each state encapsulates specific logic for data polling, streaming API connections, and transition conditions. For example, the process transitions from `:online` to `:driving` when the vehicle begins moving, while the `:charging` state handles power flow monitoring and charge session tracking.

### Public API and Messaging

Public functions provide a clean interface for interacting with vehicle processes:

- `summary/1` retrieves current vehicle state via `GenStateMachine.call/2`
- `suspend_logging/1` and `resume_logging/1` control data collection
- `subscribe_to_summary/1` integrates with Phoenix PubSub for real-time updates

### Circuit Breakers for API Resilience

To handle Tesla API instabilities, the vehicle process installs two fuse circuits—`:vehicle_not_found` and `:api_error`. When repeated failures blow these fuses, the supervisor kills and restarts the entire fleet, forcing a fresh connection to the Tesla API rather than allowing cascading failures.

## Integration with Supporting GenServers

The vehicle processes coordinate with specialized GenServers for cross-cutting concerns.

### MQTT Publishing

The `TeslaMate.Mqtt.Publisher` GenServer, defined in [`lib/teslamate/mqtt/publisher.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/mqtt/publisher.ex), handles all MQTT message publishing. Vehicle processes communicate with this server via `GenServer.call/3` to broadcast telemetry data to external systems.

### Token Management and Updates

`TeslaMate.Vault` (in [`lib/teslamate/vault.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vault.ex)) stores API tokens in a centralized GenServer using `use GenServer`, ensuring all vehicle processes use valid authentication without duplicating token state. Additionally, `TeslaMate.Updater` (in [`lib/teslamate/updater.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/updater.ex)) runs as a separate GenServer under the application supervisor to periodically check for new TeslaMate releases.

## Practical Implementation Examples

The following examples demonstrate how to interact with the supervision tree and vehicle processes at runtime:

```elixir

# Starting the vehicle supervisor (typically done at application boot)

{:ok, _pid} = TeslaMate.Vehicles.start_link(name: TeslaMate.Vehicles)

# Dynamically adding a new vehicle to the supervision tree

vehicle_spec = TeslaMate.Vehicles.Vehicle.child_spec(car: %Car{id: 42, name: "Model 3"})
{:ok, _pid} = Supervisor.start_child(TeslaMate.Vehicles, vehicle_spec)

# Querying vehicle state via the GenStateMachine API

%Vehicle.Summary{} = TeslaMate.Vehicles.summary(42)

# Suspending data collection for a specific vehicle

:ok = TeslaMate.Vehicles.suspend_logging(42)

# Restarting the entire fleet (useful after configuration changes)

TeslaMate.Vehicles.restart()

```

## Summary

- **Process Isolation**: Each vehicle operates as a separate `GenStateMachine` process in [`lib/teslamate/vehicles/vehicle.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles/vehicle.ex), ensuring faults remain localized and do not crash the entire fleet.
- **Supervision Tree**: The `TeslaMate.Vehicles` supervisor uses a `:one_for_one` strategy to automatically restart failed vehicle processes, maintaining continuous data collection.
- **State-Driven Design**: Finite state machines cleanly separate concerns between driving, charging, sleeping, and offline states, simplifying complex polling logic in `handle_event/4`.
- **Dynamic Scalability**: Adding vehicles requires only adding new child specifications to the supervisor, allowing the system to scale without architectural changes.
- **Operational Control**: Functions like `kill/0` and `restart/0` in [`lib/teslamate/vehicles.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles.ex) enable graceful fleet-wide restarts for configuration reloads or API reconnection.

## Frequently Asked Questions

### What is the difference between GenServer and GenStateMachine in TeslaMate?

While both are built on GenServer, `GenStateMachine` (used in [`lib/teslamate/vehicles/vehicle.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles/vehicle.ex)) provides explicit state handling through `handle_event/4` callbacks. This allows TeslaMate to model complex vehicle lifecycle states—such as transitioning from `:online` to `:driving` to `:charging`—more cleanly than a standard GenServer, which would require manual state tracking in the process dictionary.

### How does TeslaMate handle a crashed vehicle process?

The `TeslaMate.Vehicles` supervisor implements a `:one_for_one` restart strategy. When a vehicle process crashes, the supervisor automatically restarts only that specific process using the original child specification from `TeslaMate.Vehicles.Vehicle.child_spec/1`, leaving all other vehicle processes unaffected and maintaining data continuity for the rest of the fleet.

### Can TeslaMate manage multiple vehicles simultaneously?

Yes. The supervision tree is designed for dynamic scalability. Each vehicle gets its own named process (e.g., `:"42"` for vehicle ID 42), and the supervisor in [`lib/teslamate/vehicles.ex`](https://github.com/teslamate-org/teslamate/blob/main/lib/teslamate/vehicles.ex) can manage dozens of concurrent vehicle processes. Adding a new vehicle simply requires starting a new child under the existing supervisor.

### What happens when the Tesla API returns repeated errors?

The vehicle process implements circuit breaker patterns using fuse circuits named `:vehicle_not_found` and `:api_error`. When these fuses blow due to repeated API failures, the supervisor kills and restarts the entire vehicle fleet. This forces a clean reconnection to the Tesla API rather than allowing the system to persist in a degraded state with invalid authentication or stale connections.