![]() |
VOOZH | about |
Database auditing is a cornerstone of enterprise security, providing the necessary traceability to meet global compliance standards like GDPR. This guide explores how to implement and optimize auditing in both MongoDB Atlas and self-managed Enterprise environments, ensuring comprehensive visibility into user activity without compromising cluster performance.
Once enabled, MongoDB Atlas starts collecting audit events and stores them securely, separate from operational logs. Auditing is available only on M10+ clusters and may incur additional costs depending on log volume.
How to enable auditing on self-managed MongoDB servers
For self-managed deployments, you enable auditing via the configuration file (mongod.conf). This allows you to choose where logs are sent: the console, a JSON/BSON file, or the system syslog.
To enable file-based JSON auditing, add this to your configuration files in the nodes of your cluster:
auditLog:
destination: file
format: JSON
path: /folder/auditLog.json
After making the change, restart the mongod services of each node, one at the time. You might want to set runtimeConfiguration too. Before restarting, see Configuring filters on self-managed MongoDB clusters.
What you should audit depends on what data you handle and your goals.
We can divide audits into three categories:
| TableChecks | Failed | Succeed |
|---|---|---|
| Authentication | Track failed login attempts if you want to identify authentication attacks | Track successful logins if interested in who accessed your cluster and when |
| Administrative actions | Track if interested in attempts by users to do something they don't have permission to perform | Track successful administrative operations if interested in who and when they were done |
| AuthChecks (CRUDs) | Track if interested in attempts by users to do something they don't have permission to perform | Track only if needed, and only essential collections CRUD; tracking all successful CRUD operations will degrade performance |
Auditing everything can create a volume of logs difficult to read and cause a performance degradation. This is why we advise audit AuthChecks (CRUDs) sparingly. Logging every successful find or update on a high-traffic collection can significantly impact performance. Use it only for highly sensitive collections like user passwords or financial records. Remember that to add a further level of security on sensitive data, you can also use client-side field-level encryption (CSFLE).
Auditing everything can create massive log files and overhead. Filtering allows you to capture only the "interesting" events, saving storage costs, making analysis easier, and saving your MongoDB instance's performance.
For self-managed servers, there are two ways to filter audit events. The recommended approach is to define and modify the filter at runtime. Alternatively, you can set the filter in your configuration file, but this requires editing each configuration file and restarting the cluster nodes to make subsequent changes.
Runtime configuration (MongoDB 5.0+):
In the configuration file (mongod.conf), set auditLog.runtimeConfiguration: true:
auditLog:
destination: file
format: JSON
path: /folder/auditLog.json
runtimeConfiguration: true
After making the change, restart the mongod services of each node, one at a time.
From this moment on, to change the audit filter, use the following command from mongoshell:
db.adminCommand( { setClusterParameter: { auditConfig: <value> } } )
To view the current filter, use:
db.adminCommand( { getClusterParameter: "auditConfig" } )
If you want to audit also successful AuthChecks (CRUDs), use this command:
db.adminCommand( { setParameter: 1, auditAuthorizationSuccess: true } )
Static configuration
Define the filter in your configuration file (mongod.conf) using the filter field under auditLog:
auditLog:
destination: file
format: JSON
path: /folder/auditLog.json
filter: 'your filter'
After making the change and after any future change of the filter, restart the mongod services of each node, one at a time.
If you want to audit also successful AuthChecks (CRUDs), use this command in a connected mongoshell:
db.adminCommand( { setParameter: 1, auditAuthorizationSuccess: true } )
Whether you are on MongoDB Atlas or on-premises, the filter syntax is the same. The JSON filter contains MongoDB Query Language, like the one you use in find queries or aggregate $match stages. It operates on audit logs whose structure can be seen in the section Anatomy of an audit log entry.
For example, to log CRUD operations to the collection personalData of the database users, we defined this in the JSON filter:
{
"atype": "authCheck", # Action type, CRUDs
"param.ns": "users.personalData", # db.collection
"param.command": { # specific commands to audit
"$in": [
"aggregate",
"count",
"distinct",
"group",
"mapReduce",
"geoNear",
"geoSearch",
"eval",
"find",
"getLastError",
"getMore",
"getPrevError",
"parallelCollectionScan",
"delete",
"findAndModify",
"insert",
"update",
"resetError"
]
}
}
A full list of filters can be found on the Configure Audit Filters MongoDB documentation page.
To access your audit logs in MongoDB Atlas, simply:
Note that logs are retained for 30 days.
A MongoDB audit log is a JSON object defined in the documentation page MongoDB Schema Audit Messages. An Open Cybersecurity Schema Framework (OCSF) can be used, but it is out of the scope of this guide.
Understanding the structure is key to troubleshooting and filtering.
| Field | Description |
|---|---|
| atype | The action type, for example, authenticate, authCheck (CRUDs), createCollection |
| ts | The timestamp of the event |
| users | The identity of the user performing the action |
| roles | The roles of the user performing the action |
| remote | The IP address and port of the client |
| param | Details of the operation, for example, the database and collection name, the operation performed |
| result | The exit code |
The example below shows that the analyst has successfully accessed our personalData collection as they have access to all databases:
{
"atype": "authCheck",
"ts": {
"$date": "2026-01-19T08:10:06.341+00:00"
},
//...
"remote": {
"ip": "104.30.162.12",
"port": 76350
},
"users": [
{
"user": "analyst",
"db": "admin"
}
],
"roles": [
{
"role": "readWriteAnyDatabase",
"db": "admin"
}
],
"param": {
"command": "find",
"ns": "users.personalData",
"args": {
"find": "personalData",
"filter": {},
//...
"$db": "users"
}
},
"result": 0
}
The logs themselves can become a security risk. If a user runs a query containing a Social Security Number (SSN) or a password in plain text, that sensitive data might be recorded in the audit log.
Log redaction prevents this by masking the command and param fields in the audit output. When enabled, MongoDB replaces sensitive values with placeholders, ensuring that even if an attacker gains access to your logs, they cannot see the actual data being queried.
To activate it in MongoDB Atlas:
Enabling this will trigger a rolling restart of your cluster as the configuration change is applied to each node.
The equivalent configuration for self-managed Enterprise clusters is:
security:
redactClientLogData: true
As we have explored, the goal is not to log every single operation, which can lead to performance bottlenecks and a huge amount of logs, but to capture high-value events that tell a clear story of your data's lifecycle. When configured correctly, it can transform a black box database into a compliant and transparent one.
runtimeConfiguration: true is enabled. This allows changes using the setClusterParameter command without restarting nodes.