Start from the contract
A Spring Boot API is easy to start and easy to tangle. The difference is whether you design the resource contract before filling controllers with business logic.
Name resources after the domain: products, clients, orders. Keep verbs in HTTP methods, not in URL paths, unless you are modeling a genuine operation.
Keep the layers honest
A practical structure looks like this:
- Controllers translate HTTP into application calls
- Services contain use-cases and rules
- Repositories talk to persistence
If a controller starts assembling SQL-shaped logic, the API will become difficult to test and difficult to change. If a repository starts making HTTP decisions, the persistence layer will leak into every client.
Validation belongs at the boundary
Use request validation for shape and required fields. Use service-level checks for business conflicts that the JSON schema cannot see.
Return errors that a client can handle. A 400 with a clear message is more useful than a 500 caused by a null field you could have rejected earlier.
Persistence is not the domain
PostgreSQL should store the data. It should not be the only place the rules live. Constraints are valuable, but the application still needs to explain why a write was rejected.
This also keeps H2 or another test database usable. If every rule is a proprietary SQL feature, the test environment stops representing the application.
Document the contract
API documentation is part of the interface. If the only way to understand an endpoint is to read a controller, frontend work becomes archaeology.
Document the resource, the error model, and the authentication requirements. Keep that documentation close to the code so it cannot drift in silence.
What to postpone
Do not add a gateway, a message broker, and a custom exception taxonomy on the first day. Get the resources right. Make the happy path and the validation path explicit. Then grow.
Related articles

Building a content-driven Next.js UI
How to keep React components reusable by pushing portfolio content behind a data access layer.

Understanding OpenTelemetry
A practical introduction to traces, metrics, and why instrumentation should be part of the service, not a later operations task.
