Go architectures · 3 MIN READ
Vertical slices: organize around a use case
Keep feature changes together without duplicating shared invariants.
Keep feature changes together without duplicating shared invariants. A vertical slice groups request parsing, application behavior and persistence for one capability, such as RenameProject. Trace the worked Go example, then compare the benefit with the cost before applying this design to your own project.
Architecture · A MAP OF THE IDEA
- Rename request
- RenameProject validation
- Persist the renamed project
Useful when
- Most changes affect one feature
- A team wants short paths from endpoint to behavior
Watch out
- Cross-feature invariants need explicit ownership
- Uncontrolled duplication can drift
Implementation & operation cost: Medium
Fit depends on the task
Editorial suitability, not benchmarks or a universal ranking. Styles describe different axes and can be combined.
The design decision
A vertical slice groups request parsing, application behavior and persistence for one capability, such as RenameProject. It can live inside a modular monolith and still call shared domain rules. It describes organization by change, not a new deployment topology.
A complete Go example
Read this program from the entry point and follow the calls shown in the diagram. The output is included at the end so you can check the behavior without a compiler.
package main
import (
"errors"
"fmt"
"strings"
)
type Project struct{ Name string }
func RenameProject(p *Project, raw string) error {
name := strings.TrimSpace(raw)
if name == "" {
return errors.New("name required")
}
p.Name = name
return nil
}
func main() {
p := Project{Name: "Draft"}
fmt.Println(RenameProject(&p, " Library "))
fmt.Println(p.Name)
}
// Output:
// <nil>
// Library
RenameProject owns normalization and validation for one operation. The caller receives an error rather than modifying Name itself. A larger slice can include its HTTP DTO and SQL query without routing through layers that only forward arguments.
Tradeoffs and the simpler alternative
Extract a shared domain rule when several slices genuinely enforce the same invariant. Duplicated validation can drift, while an overgeneralized framework can make every change harder. Slices can share infrastructure without sharing their entire application model.
Organize by the change a user requests
Keep the command or query, validation, handler and response mapping for PlaceOrder close together. Share domain rules when they genuinely apply across use cases, not because two DTOs happen to have similar fields. A slice can use a concrete store for a simple query and a richer domain model for a complex command. Vertical slices describe the direction of code organization; they can run in one process and do not imply a service for each endpoint.
Make shared policy explicit
Authentication, authorization, observability and transaction management should have one understandable integration point. Keep endpoint-specific authorization near the use case when permission depends on loaded domain state. Avoid a global pipeline that catches and suppresses every error or makes transaction lifetime invisible. Two slices updating the same invariant need coordinated ownership, even if their files are in separate folders. Duplicating business rules across slices creates divergent behavior.
Test one slice end to end at its boundary
For a command, test invalid input, denied access, success and a failed durable write. For a query, test filtering and response shape without constructing unrelated domain workflows. Preserve the public route and event contracts while reorganizing packages. Extract shared code only after repeated changes reveal one stable responsibility. This approach makes feature changes local but needs conventions so each slice does not invent different error, logging and validation behavior.
TAKE THIS WITH YOU
Group code by use case and reason to change. Extract a shared domain rule when several slices genuinely enforce the same invariant. Duplicated validation can drift, while an overgeneralized framework can make every change harder. Slices can share infrastructure without sharing their entire application model.
Check your understanding
Which statement best describes Vertical slices: organize around a use case?
Go to the source
Progress stays in this browser. No account needed.