# Package by feature

> Organise code by business capability rather than technical layer, so a change to one feature stays in one place and boundaries can be enforced.

Concept · Architecture & domain modeling · https://levelcode.org/concepts/package-by-feature

**Package by layer** groups code by technical role: all handlers together, all services together, all repositories together. **Package by feature** groups it by what it does for the business: everything about orders together, everything about payments together.

```text
By layer                         By feature
internal/                        internal/
  handlers/  order.go user.go      ordering/  handler.go service.go store.go
  services/  order.go user.go      accounts/  handler.go service.go store.go
  repos/     order.go user.go      payments/  handler.go service.go store.go
  models/    order.go user.go      platform/  database/ httpserver/ config/
```

## Why feature packages scale better

- **Changes stay local.** Adding a field to orders touches one directory instead of four. That's high [cohesion](https://levelcode.org/concepts/coupling-and-cohesion): code that changes together lives together.
- **Encapsulation becomes possible.** In a layered layout, everything in `models` must be exported for `handlers` and `services` to use it, so every feature can reach every other feature's internals. In a feature package, most identifiers can stay unexported, and Go's `internal/` directories can hide a feature's implementation from the rest of the codebase entirely.
- **The structure tells you what the system does.** A newcomer reading `ordering/`, `payments/`, `delivery/` learns the business; reading `handlers/`, `services/` learns nothing.
- **Ownership is clear.** A team can own a directory, and boundaries map naturally onto [bounded contexts](https://levelcode.org/concepts/bounded-contexts) or future services.

Layers don't disappear — they move **inside** each feature, where they still separate HTTP from logic from storage.

## In practice

- Keep shared infrastructure (database connection, HTTP server setup, config) in a `platform` package that features depend on, never the reverse.
- Avoid catch-all `utils` or `common` packages; put helpers in the feature that uses them, or name a package for what it does (`money`, `slug`).
- When features need each other, go through a small public API rather than reaching into implementation files.
- Large apps go further and split each feature into **api** and **implementation** modules, so features depend only on each other's APIs — the pattern used by large Android and Gradle codebases.

Very small services can stay flat in one package; feature packages pay off once there are several distinct capabilities. See the [modular design lesson](https://levelcode.org/roadmaps/software-engineer/modular-design).
