Give an application user read or readWrite on the one database it uses, nothing broader. Roles that look administrative, such as userAdmin on the admin database or userAdminAnyDatabase, let the holder grant themselves any privilege, so they belong to people, not applications.
How roles are scoped
MongoDB's documentation says each built-in role defines access at the database level for all non-system collections in the role's database. A role is attached to a user together with the database it applies to, so the same role name means different reach depending on where you assign it. That is why a role name alone tells you little during a review.
You can inspect the exact privileges of any role with rolesInfo or db.getRole using showPrivileges and showBuiltinRoles. Do that before approving an unfamiliar grant.
The roles most apps need
readfor reporting jobs and dashboards that never write.readWritefor the application's own database. It includes allreadprivileges plus the ability to modify data on non-system collections.
If you want something narrower, such as one collection, create a custom role with exactly those privileges rather than stretching a built-in one.
The roles that are really admin power
The documentation's superuser section is blunt. These let a holder assign themselves any privilege on any database:
dbOwnerscoped to the admin databaseuserAdminscoped to the admin databaseuserAdminAnyDatabase
userAdmin on an ordinary database lets the user grant themselves any privilege on that database. dbOwner combines readWrite, dbAdmin and userAdmin, so handing it to an application because it is convenient gives the app account control over user management too. The root role provides full privileges on all resources.
A practical grant pattern
- One admin identity for user management, kept out of application configs and used rarely.
- One
readWriteuser per application, scoped to its own database. - One
readuser for analytics and support tooling. - A calendar reminder to review users, as the security checklist advises.
Separate users also make logs readable. When an unexpected delete shows up, you want to know which service issued it.
Audit what exists today
List users and their roles and look for three patterns: application accounts with dbOwner, any account with a role granted on the admin database that was not meant for administrators, and old accounts nobody can name an owner for. Fix the first two by creating a narrower user, switching the app over, then dropping the old one. Do not edit a live production grant without a rollback plan.
Related: MongoDB access control and bindIp.
Quick check
Is readWrite safe for an application account?
It is the usual choice when scoped to the single database the app owns. Avoid assigning it on the admin database or through any-database variants unless required.
Why is userAdmin considered high risk?
The documentation says it allows users to grant any privilege to any user, including themselves, so it indirectly provides superuser access.
Sources
Last reviewed: 19 October 2026.