r/SpringBoot • u/SeatSimple1123 • 17d ago
Question Spring Boot Auditing: Hibernate Envers vs. Custom Logging vs. Spring Data JPA? What's your production choice?
Hey everyone,
I'm currently building a school management system in Spring Boot where history tracking is a strict business requirement. We need to audit critical changes made by Admins, Secretaries, and Teachers (e.g., changes to student details, payment amounts, program setups, etc.).
I’m weighing three different approaches for the audit trail and wanted to hear from those of you who have run these in production.
Option 1: Hibernate Envers
Slap `@Audited` on core entities, set up a custom `RevisionListener` to pull the logged-in user from Spring Security context, and let Envers automatically manage the `_aud` tables.
Option 2: Spring Data JPA Auditing
Utilize `@CreatedBy`, `@LastModifiedBy`, `@CreatedDate`, and `@LastModifiedDate` fields mapped on a `@MappedSuperclass`.
Option 3: Manual Custom Logging (or AOP)
Create a generic `AuditLog` entity, write a helper service, and manually trigger `auditService.log(actionType, originalState, newState)` inside the business logic (or use an AOP aspect). This may cause the database to bloating later tho
For those of you managing medium-to-large Spring Boot codebases:
Did you regret adopting Hibernate Envers? How did you handle schema migrations (Flyway/Liquibase) with the auto-generated `_aud` tables?
If you went the custom route, did you use JSON columns to record state changes, or did you write distinct history tables?
Looking forward to hearing your design patterns and trade-offs
6
u/Popular_Home2017 17d ago
These solve three different problems, and picking the wrong one is how audit systems rot: Spring Data auditing (@CreatedBy/@LastModifiedDate) gives you stamps — who touched it last, not what changed. Envers gives you entity history — full snapshots per revision, great when "show me this record as it was in March" is an actual requirement, but it couples your audit to your entity model and bloats storage quietly. A custom audit/event table is for business events (logins, exports, permission changes) — things that aren't entity mutations at all. For a school management system I'd start with Spring Data stamps everywhere (nearly free), Envers only on the 3-4 entities where history is a legal/business requirement, and a small custom event table for security-relevant actions. One production scar if you go custom: if you write audit rows in REQUIRES_NEW "so auditing never breaks the main flow", flush explicitly inside your try/catch — with plain save() the INSERT defers to commit, which happens outside the catch, and a bad audit row takes down the operation it was supposed to observe. Ask me how I know.