How the Fuse Circuit Breaker Protects Against Tesla API Rate Limiting in TeslaMate

TeslaMate uses the Erlang fuse library to implement a circuit-breaker pattern that immediately blocks API requests after detecting a 429 Too Many Requests response, preventing the application from hammering Tesla's rate-limited endpoints.

The teslamate-org/teslamate repository relies on aggressive rate limiting protection to maintain stable synchronization with the Tesla Owner API. By wrapping every vehicle API call in a circuit breaker, the system automatically enters a fail-fast state when throttling occurs, respecting Tesla's API constraints without manual intervention. This implementation ensures that temporary rate limits don't cascade into application-wide failures during heavy polling scenarios.

Circuit Breaker Architecture

TeslaMate implements the classic circuit-breaker pattern using the fuse library (version 2.5). When the Tesla API returns a 429 Too Many Requests error—or any other throttling indicator—the corresponding fuse "blows" and immediately short-circuits subsequent requests for that specific vehicle.

Fuse Installation and Configuration

During vehicle process initialization in lib/teslamate/vehicles/vehicle.ex, TeslaMate installs and enables two distinct fuses per vehicle:

fuses = [
  {:api_error, {{:standard, 2, :timer.minutes(3)}, {:reset, :timer.minutes(15)}}},
  {:vehicle_not_found, {{:standard, 1, :timer.minutes(5)}, {:reset, :timer.minutes(30)}}}
]

for {key, opts} <- fuses do
  name = fuse_name(key, data.car.id)
  :ok = :fuse.install(name, opts)
  :ok = :fuse.circuit_enable(name)
end

(source: lib/teslamate/vehicles/vehicle.ex, lines 198–206)

The :api_error fuse uses a standard tolerance of 2 failures within 3 minutes, with an automatic reset period of 15 minutes. This configuration allows brief transient errors while immediately protecting against sustained rate limiting.

Blowing the Fuse on API Errors

When an API request returns a throttling error, TeslaMate disables the circuit and melts the fuse to initiate the backoff period:


# Disable the circuit immediately upon detecting API throttling

:ok = fuse_name(:api_error, data.car.id) |> :fuse.circuit_disable()

# Later, after the backoff period, melt the fuse to trigger reset logic

:ok = fuse_name(:api_error, data.car.id) |> :fuse.melt()

(source: lib/teslamate/vehicles/vehicle.ex, lines 485–514)

The circuit_disable/1 call ensures no new requests enter the pipeline, while melt/1 signals the fuse system to begin the cooldown timer.

Short-Circuiting Requests

Every API call first queries the fuse state before reaching the Tesla servers. If the fuse is blown, the call aborts immediately with a :blown response:

with :ok <- :fuse.ask(fuse_name(:api_error, car_id), :sync) do
  # Perform the actual Tesla API request only if fuse is closed

  TeslaApi.request()
else
  :blown -> {:error, :rate_limited}
end

(source: lib/teslamate/vehicles/vehicle.ex, lines 149–152)

This pattern eliminates unnecessary network traffic during active rate limiting, reducing load on both TeslaMate and the Tesla API infrastructure.

Implementation Example

The following function demonstrates production-grade fuse handling when fetching vehicle state data:

def fetch_vehicle_state(car_id) do
  fuse = fuse_name(:api_error, car_id)

  case :fuse.ask(fuse, :sync) do
    :ok ->
      # Fuse is closed – safe to call the API

      TeslaApi.Vehicle.get_state(car_id)

    :blown ->
      # Fuse is blown – skip the call and return rate-limit error

      {:error, :rate_limited}
  end
end

If you need to manually reset a fuse outside the automatic timer (rarely required), use:

def reset_api_fuse(car_id) do
  :fuse.reset(fuse_name(:api_error, car_id))
end

Key Source Files

  • lib/teslamate/vehicles/vehicle.ex – Core implementation containing fuse installation, the fuse_name/2 helper, and circuit state management logic.
  • mix.exs – Declares the {:fuse, "~> 2.5"} dependency required for the circuit-breaker functionality.
  • lib/teslamate/api.ex – Contains additional fuse implementations for generic API endpoints, including the :unauthorized fuse.
  • test/teslamate/vehicles/vehicle_test.exs – Validates fuse behavior including circuit disabling, melting, and automatic reset timers.

Summary

  • Automatic protection: The fuse circuit breaker activates immediately upon receiving HTTP 429 responses, preventing request storms against rate-limited Tesla API endpoints.
  • Configurable backoff: The :api_error fuse tolerates 2 failures per 3-minute window and enforces a 15-minute cooldown before retrying.
  • Zero-overhead short-circuiting: Blown fuses return :blown status locally without network latency, conserving resources during API throttling events.
  • Per-vehicle isolation: Each vehicle maintains independent fuses via the fuse_name/2 function, ensuring one throttled vehicle doesn't affect others.

Frequently Asked Questions

How does the fuse circuit breaker differ from simple retry logic?

Unlike naive retry loops that continuously hammer rate-limited endpoints, the fuse circuit breaker immediately fails fast for a configurable duration after detecting throttling. This respects Tesla's API limits by enforcing a mandatory cooling-off period rather than retrying blindly.

Can I adjust the rate limiting sensitivity?

Yes. Modify the fuse configuration tuple in lib/teslamate/vehicles/vehicle.ex line 199. The format {{:standard, max_failures, time_window}, {:reset, cooldown_period}} allows tuning of failure tolerance and reset intervals to match Tesla's current API policies.

What happens if the fuse blows for one vehicle but not others?

TeslaMate uses the fuse_name/2 function to create isolated fuse instances per vehicle ID. If vehicle A triggers rate limiting, only vehicle A's fuse blows; vehicles B, C, and D continue normal operation unaffected.

Does TeslaMate automatically recover after the fuse blows?

Yes. The fuse system includes an automatic reset timer configured via :timer.minutes(15) in the installation options. Once the cooldown elapses, :fuse.ask/2 returns :ok again and normal API polling resumes without manual intervention.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →