Skip to content

Roadmap

Ferro is pre-1.0 and under active development. The items below are known gaps we intend to close; priorities are driven by what users actually hit, so issues move things up this list.

Query Features

  • having() — post-aggregation filtering for grouped queries; where() rejects aggregate predicates pointing at it (#291). Workaround: filter groups in Python after all().
  • Typed record fields — a projected Row's fields type as Any on access today; inferring per-field types from the selector (so row.total checks as int | None) is #290.
  • Reverse and many-to-many populationinclude() populates forward-FK paths in one statement; populating BackRef collections and M2M sets is a separate future mechanism (a batched second query stitched onto the results). Today each awaited collection is its own query. (Filtering on reverse/M2M membership already works — the existence test, t.lines.exists(...).)
  • Cross-scope correlation in existence tests — comparing an inner-lambda column against the outer scope (t.lines.exists(lambda line: line.category_id == t.category_id)) is rejected at build time today; correlated column-to-column comparison is #309.
  • ilike() — case-insensitive pattern matching. Workaround: like() with normalized case.
  • Atomic update expressions — database-side expressions in batch updates, e.g. update(view_count=Post.view_count + 1), avoiding the read-modify-write race. Workaround today: load, mutate, save() (or raw SQL).

Connections

  • disconnect() — graceful pool shutdown for application shutdown hooks. Today cleanup happens at process exit.
  • Health checks — a check_connection()-style probe for readiness endpoints. Workaround: run a trivial query and catch the failure.
  • Richer pool configurationPoolConfig covers max_connections/min_connections today; acquire timeouts, idle timeouts, and max connection lifetime are future work.

Influencing Priorities

None of this is on a promised schedule. If one of these gaps blocks you, say so on the issue tracker — a concrete use case is the strongest signal we get, and contributions are welcome.