Spring Boot Auditing (JPA, MongoDB, and Microservices)
Auditing tracks who created/modified a record and when.
Enabling JPA Auditing
Section titled “Enabling JPA Auditing”@EnableJpaAuditing@SpringBootApplicationpublic class Application {}Auditable Base Entity
Section titled “Auditable Base Entity”@MappedSuperclass@EntityListeners(AuditingEntityListener.class)public abstract class Auditable {
@CreatedBy private String createdBy;
@CreatedDate private LocalDateTime createdDate;
@LastModifiedBy private String modifiedBy;
@LastModifiedDate private LocalDateTime modifiedDate;}Extending the Base Entity
Section titled “Extending the Base Entity”@Entitypublic class Order extends Auditable {
@Id private Long id;}Providing the Current Auditor
Section titled “Providing the Current Auditor”@Beanpublic AuditorAware<String> auditorProvider() { return () -> Optional.of("currentUser");}Spring automatically populates:
createdBycreatedDatemodifiedBymodifiedDate
Auditing Annotations
Section titled “Auditing Annotations”| Annotation | Purpose |
|---|---|
@CreatedBy |
User who created the entity |
@CreatedDate |
Creation timestamp |
@LastModifiedBy |
Last user who updated |
@LastModifiedDate |
Last modification timestamp |
@EntityListeners(AuditingEntityListener.class) |
Enables entity auditing |
Example:
@CreatedDateprivate LocalDateTime createdAt;
@LastModifiedDateprivate LocalDateTime updatedAt;Auditing in MongoDB
Section titled “Auditing in MongoDB”Enable auditing:
@EnableMongoAuditing@Configurationpublic class MongoConfig {}Document:
@Documentpublic class Product {
@Id private String id;
@CreatedDate private Instant createdDate;
@LastModifiedDate private Instant modifiedDate;
@CreatedBy private String createdBy;}Auditor provider:
@Beanpublic AuditorAware<String> auditorProvider() { return () -> Optional.of("systemUser");}Customizing Auditing
Section titled “Customizing Auditing”Custom AuditorAware
Section titled “Custom AuditorAware”public class SpringSecurityAuditorAware implements AuditorAware<String> {
@Override public Optional<String> getCurrentAuditor() { Authentication auth = SecurityContextHolder.getContext().getAuthentication(); return Optional.of(auth.getName()); }}Other Customizations
Section titled “Other Customizations”- Store
tenantId,createdByUserId,createdByRole - Persist audit history using Hibernate Envers, custom listeners, or CDC (e.g., Debezium)
- Capture metadata such as IP address, request ID, and service name
Change Data Capture (CDC) streams row-level database changes directly, without requiring application code to publish audit events:
flowchart LR
DB[(Database)] --> D[Debezium]
D --> K[Kafka]
K --> A[Audit Service]
Centralized Auditing in Microservices
Section titled “Centralized Auditing in Microservices”Each service owns its own database, making cross-service auditing challenging.
Event-Driven Audit Architecture
Section titled “Event-Driven Audit Architecture”flowchart LR
Client --> Gateway["API Gateway"]
Gateway --> Order["Order Service"]
Gateway --> Payment["Payment Service"]
Gateway --> User["User Service"]
Order --> Kafka["Kafka / RabbitMQ"]
Payment --> Kafka
User --> Kafka
Kafka --> Audit["Central Audit Service"]
Audit --> AuditDB["Audit Database"]
Example audit event:
{ "entity": "Order", "entityId": "123", "operation": "UPDATE", "user": "admin", "timestamp": "2026-03-16", "service": "order-service"}Benefits:
- Centralized history
- Cross-service traceability
- Loose coupling
- Scalable event-driven architecture
Key Takeaways
Section titled “Key Takeaways”- Spring Data provides built-in auditing for JPA and MongoDB via
@CreatedBy,@CreatedDate,@LastModifiedBy,@LastModifiedDate. AuditorAwaresupplies the current user; a Spring Security-backed implementation resolves it from the security context in real applications.- In microservices, each service owning its own database makes cross-service auditing hard — a centralized audit service consuming events from Kafka/RabbitMQ solves this without tight coupling.