one_flight should stay small: the core package is a request-coalescing primitive, not a cache, HTTP client, retry library, or JSON library. Integrations should be added only when they make the primitive easier to apply without weakening that boundary.

v0.1: Single-node core

Status: implemented.

v0.2: Cluster scope

Goal: keep the same call-site API while coalescing duplicate calls across a connected Elixir cluster.

  • Add scope: :cluster.
  • Use the two-level design:
    • level 1: local singleflight per node
    • level 2: only local leaders enter cluster coordination
  • Use :global name registration for level-2 coordination.
  • Keep closures local; user functions never cross the wire.
  • Add :peer tests for simultaneous candidates, leader-node death, and netsplit behavior.
  • Document the honest guarantee: at most one execution per connected partition in steady state, with duplicate windows during membership changes.

v0.3: Req integration

Goal: make outbound HTTP request coalescing ergonomic for projects that already use Req.

Likely shape:

Req.new()
|> OneFlight.Req.attach(name: MyApp.Flights, key: :url)
|> Req.get!(url: url)

Use cases:

  • duplicate GET requests to the same upstream resource
  • rate-limited APIs
  • remote configuration fetches
  • token introspection
  • service discovery endpoints

The integration should let callers choose the key strategy, such as URL only, method plus URL, or method plus URL plus request body hash.

v0.4: Finch examples or helper

Goal: support lower-level HTTP users without forcing a Req dependency.

Start with README examples:

OneFlight.run({:http, :get, url, headers_hash}, fn ->
  Finch.build(:get, url, headers)
  |> Finch.request(MyFinch)
end, name: MyApp.Flights)

Only add a dedicated helper if real users ask for it. A OneFlight.Finch module is less obviously valuable than a Req step because Finch intentionally has a small low-level API.

Poison and JSON workloads

Poison is a use case, not an integration target.

Good uses:

  • coalesce loading and decoding the same large remote JSON config
  • avoid duplicate parse work after a cache miss
  • dedupe expensive schema/source transformations keyed by content hash

Avoid a OneFlight.Poison module unless a concrete repeated pattern appears. JSON libraries are easy to wrap with OneFlight.run/3 directly.

Possible later work

  • strategy: :ring for large clusters where :global coordination becomes a measured bottleneck.
  • OneFlight.Req request-key presets for common safe cases.
  • Markdown report or telemetry example snippets for observability docs.
  • Benchmarks comparing duplicate uncoalesced work vs one_flight under hot keys.

Explicit non-plans

  • No result TTL.
  • No persistent storage.
  • No retry, backoff, or circuit breaking.
  • No cache API.
  • No distributed consensus dependency.