ToxiproxyEx

Resilience testing for Elixir applications

ToxiproxyEx


Looking for the library?

If you’re just looking for the library, check out ToxiproxyEx on GitHub or install it from Hex.


What is ToxiproxyEx?

ToxiproxyEx is an Elixir API client for Toxiproxy, the resilience testing tool created by Shopify.

Toxiproxy is a TCP proxy that lets you simulate network and system conditions like latency, timeouts, and connection failures. The Elixir API makes it simple to write tests that ensure your application behaves appropriately under harsh conditions.

Why Resilience Testing?

Modern applications depend on numerous external services — databases, caches, APIs, and more. When these services experience issues (and they will), your application should handle them gracefully. ToxiproxyEx helps you verify that it does.

Usage Examples

Simulating Database Latency

ToxiproxyEx.get!(:mysql_master)
|> ToxiproxyEx.toxic(:latency, latency: 1000)
|> ToxiproxyEx.apply!(fn ->
  Repo.all(Shop) # this took at least 1s
end)

Taking a Service Down

ToxiproxyEx.get!(:mysql_master)
|> ToxiproxyEx.down!(fn ->
  Repo.all(Shop) # this'll raise
end)

Simulating Multiple Redis Instances Being Down

ToxiproxyEx.grep!(~r/redis/)
|> ToxiproxyEx.down!(fn ->
  # any redis call will fail
end)

Asymmetric Network Conditions

Simulate a cache server that’s slow at incoming network (upstream), but fast at outgoing (downstream):

ToxiproxyEx.get!(:cache)
|> ToxiproxyEx.upstream(:latency, latency: 1000)
|> ToxiproxyEx.apply!(fn ->
  Cache.get(:omg) # will take at least a second
end)

Installation

Add toxiproxy_ex to your list of dependencies in mix.exs:

def deps do
  [
    {:toxiproxy_ex, "~> 2.0", only: :test}
  ]
end

Configuration

By default, the client communicates with Toxiproxy on http://127.0.0.1:8474, but you can configure a different host:

config :toxiproxy_ex, host: "http://toxiproxy.local:8844"

Populating Proxies

To populate Toxiproxy with your proxy configurations:

ToxiproxyEx.populate!([
  %{
    name: "mysql_master",
    listen: "localhost:21212",
    upstream: "localhost:3306",
  },
  %{
    name: "mysql_read_only",
    listen: "localhost:21213",
    upstream: "localhost:3306",
  }
])

Check out the full documentation on HexDocs and the source code on GitHub.

Keep exploring