Skip to content

Spring Boot Auditing (JPA, MongoDB, and Microservices)

Auditing tracks who created/modified a record and when.

@EnableJpaAuditing
@SpringBootApplication
public class Application {
}
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public abstract class Auditable {
@CreatedBy
private String createdBy;
@CreatedDate
private LocalDateTime createdDate;
@LastModifiedBy
private String modifiedBy;
@LastModifiedDate
private LocalDateTime modifiedDate;
}
@Entity
public class Order extends Auditable {
@Id
private Long id;
}
@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of("currentUser");
}

Spring automatically populates:

  • createdBy
  • createdDate
  • modifiedBy
  • modifiedDate
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:

@CreatedDate
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;

Enable auditing:

@EnableMongoAuditing
@Configuration
public class MongoConfig {
}

Document:

@Document
public class Product {
@Id
private String id;
@CreatedDate
private Instant createdDate;
@LastModifiedDate
private Instant modifiedDate;
@CreatedBy
private String createdBy;
}

Auditor provider:

@Bean
public AuditorAware<String> auditorProvider() {
return () -> Optional.of("systemUser");
}
public class SpringSecurityAuditorAware
implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
Authentication auth =
SecurityContextHolder.getContext().getAuthentication();
return Optional.of(auth.getName());
}
}
  • 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]

Each service owns its own database, making cross-service auditing challenging.

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
  • Spring Data provides built-in auditing for JPA and MongoDB via @CreatedBy, @CreatedDate, @LastModifiedBy, @LastModifiedDate.
  • AuditorAware supplies 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.