An exception hierarchy with one root and no depth

Eleven exception classes, all extending one application root, and no intermediate types — which turned out to be right.

interface DomainException extends Throwable {}

final class OrderNotFound extends RuntimeException implements DomainException {}
final class StockUnavailable extends RuntimeException implements DomainException {}

// what we did NOT build:
//   NotFoundException, ConflictException, ValidationException
//   as intermediate classes for every domain error to
//   extend, which is where hierarchies come from.

An intermediate class exists so a caller can catch a category, and every category we invented was really an HTTP status — which belongs in the layer that speaks HTTP, mapped from the concrete type. A flat set with a marker interface means a handler maps eleven types explicitly, which is more lines and no guessing.