Structuring a Spring Boot and Angular administrative system
How I organised business rules, permissions, and file storage while building the RADEMA administrative and HR system at LANAI SARL.
Administrative systems look simple from the outside: a few forms, a few tables, a login screen. The difficulty is never the screens — it is the rules that sit underneath them, and the fact that those rules change depending on who is logged in.
This is a short write-up of how I structured the administrative and HR system I worked on at LANAI SARL, built with Angular on the front and Spring Boot on the back.
Put the rules in the backend
The first decision was to stop expressing business rules in the interface. A disabled button is a hint, not a guarantee. Every constraint — who can create a record, which department a user may edit, whether a planning entry conflicts with an existing one — was implemented as a service-level check in Spring Boot.
The interface still hides what a user cannot do, because a screen full of forbidden actions is a bad experience. But the interface is now a projection of the rules, not their owner.
Model the permission before the feature
Role-based access is easier when the roles are designed first. In practice that meant answering three questions before writing an endpoint:
- Which roles can call this?
- Which subset of the data can each role see?
- What happens to the data when a role changes?
The third question is the one that gets skipped, and it is the one that produces inconsistent records six months later.
Keep files out of the database
Documents were stored on a dedicated server through MinIO rather than as blobs in MySQL. The database keeps the reference and the metadata; the object store keeps the bytes. Backups get faster, the schema stays readable, and serving a file no longer competes with the queries that run the application.
Containerise early, not at the end
Docker was part of the workflow from the start rather than a deployment step bolted on at the end. Each service ran in its own container with its own configuration, which made the boundaries between services real instead of theoretical. When a boundary is enforced by a container, it stops leaking.
What I would keep
Three habits carried over into everything I have built since:
- Rules belong where they cannot be bypassed.
- Permissions are part of the data model, not a decoration on top of it.
- Infrastructure decisions made early are cheaper than the same decisions made under deadline.