- Define service algebras as `trait Foo[F[_]]` with abstract `F[A]`-returning methods — the effect type `F` is left abstract for the caller to supply.
- Use `cats.Monad[F]` or more specific type class constraints (`Sync[F]`, `Async[F]`) on algebra implementations rather than concrete `IO` or `Future`.
- Wire services together in a single `Main` object where `F` is resolved to `cats.effect.IO` — keep all concretions at the outermost layer.
- Use `cats.effect.Resource[F, A]` for managed resources (database pools, HTTP clients) so acquisition and release are always paired.
- Provide a test interpreter for each algebra using `cats.effect.Ref` or `cats.data.StateT` — inject it in unit tests without touching production infrastructure.
- Avoid leaking `F[_]` constraints beyond the algebra boundary — data types returned by algebras should be plain case classes, not wrapped effects.
- Organise algebras, interpreters, and domain models in separate packages: `algebras/`, `interpreters/`, `domain/`.