Botica

Environment diagnostics, health checks, and feature flags for Elixir.

Hex VersionHex DocsLicense

Botica gives you two complementary tools:

  1. Botica.Doctor — define health checks, run them in parallel, summarise results, and optionally auto-fix failures.
  2. Botica.Flags — feature flags with an ETS backend and deterministic per-entity rollouts. No Redis. No Postgres. Just Elixir.

Installation

def deps do
[
{:botica, "~> 1.0"}
]
end

Usage — Health checks

config = %{
app_name: "myapp",
checks: [
%{
id: :postgresql,
name: "PostgreSQL",
description: "Database server is running",
priority: 1,
check: fn ->
case System.cmd("pg_isready", [], stderr_to_stdout: true) do
{_, 0} -> {:ok, "PostgreSQL is ready"}
{output, _} -> {:error, "PostgreSQL not ready: #{output}"}
end
end,
fix: fn -> {:ok, "sudo systemctl start postgresql"} end,
fix_command: "sudo systemctl start postgresql"
}
]
}
{:ok, results} = Botica.Doctor.run(config)
summary = Botica.Doctor.summary(results)
# => %{ok: 1, warning: 0, error: 0, total: 1, passed?: true}

Botica also ships predefined batteries: PostgreSQL, Redis, Memory, Disk.

Usage — Feature flags

# Define flags (typically at boot)
Botica.Flags.define(:new_dashboard, default: false)
Botica.Flags.define(:beta_search, default: true)
Botica.Flags.define(:rate_limiting, default: false, rollout: 25)
# Query
Botica.Flags.enabled?(:new_dashboard) # => false
Botica.Flags.enabled?(:beta_search) # => true
Botica.Flags.enabled?(:rate_limiting, for: current_user.id) # => true / false deterministically
# Toggle at runtime
Botica.Flags.enable(:new_dashboard)
Botica.Flags.disable(:new_dashboard)
Botica.Flags.set(:rate_limiting, rollout: 50)
# Introspection
Botica.Flags.all() # [%Flag{...}, ...]
Botica.Flags.get(:foo) # {:ok, %Flag{...}} | :error
Botica.Flags.count() # 3

Flags in the Doctor banner

The Doctor also exposes a feature-flags diagnostic — useful for botica doctor-style CLI banners:

banner = Botica.Doctor.format_flags_summary()
# Flags (3 defined):
# ✓ beta_search enabled (default: true)
# ✗ new_dashboard disabled (default: false)
# ~ rate_limiting rollout 25% (default: false)

How the flags work

Configuration

Botica.Application starts the Botica.Flags.Store automatically when you list botica as a dependency. You can customise the supervision tree by overriding mod: in your own mix.exs.

Architecture

Botica (top-level facadedefdelegates)
├── Doctor — entry point: run/1, fix/1, summary/1, health_check/1
│ ├── Batteries — predefined checks (PostgreSQL, Redis, Memory, Disk)
│ ├── Check — behaviour (Botica.Check.Behaviour) + result struct
│ ├── Runner — orchestration layer
│ │ ├── Executor — parallel execution with timeout + concurrency caps
│ │ └── Sequencer — priority sorting, tag/fixable filtering
│ ├── Repair — auto-fix orchestration (Botica.Repair.Fixer)
│ └── Flags — feature-flags diagnostic (flags_summary, format_flags_summary)
└── Flags — feature flags (define, enable, disable, rollout, etc.)
├── Flag — struct + factory with rollout clamping
└── Store — GenServer that owns the :botica_flags ETS table

Documentation

License

MIT — see LICENSE.md.