Database managementMulti-tenancy

Multi-tenancy Enterprise

Multi-tenant support in Memgraph enables users to manage multiple isolated databases within a single instance. The primary objective is to facilitate efficient resource isolation, maintain data integrity, and manage access for different clients.

All isolated databases share the underlying CPU resources. Durable storage is isolated per database — each database has its own data directory under databases/. Per-database RAM usage can be restricted using tenant profiles, which enforce a memory limit on individual databases. Without a tenant profile, global limitations are imposed on Memgraph as a whole.

Default (memgraph) database

A default database named memgraph is automatically created during startup. When you create a user or role, they have access to the default database (memgraph) by default. The default database name cannot be altered.

To remove this default access, you should use REVOKE DATABASE memgraph FROM role_name;. Using REVOKE removes the default grant but allows the role to potentially receive access through other means (e.g., if combined with another role that has access). Using DENY would explicitly forbid access regardless of other roles.

Default database best practices

In multi-tenant environments, we recommend treating the default “memgraph” database as an administrative/system database rather than storing application data in it. This approach provides better security and isolation, especially given recent changes to authentication and authorization requirements.

Why treat memgraph as an admin database?

As of Memgraph v3.5, users have to have both the AUTH privilege and access to the default “memgraph” database to execute authentication and authorization queries. Additionally, replication queries (such as REGISTER REPLICA, SHOW REPLICAS, etc.) and multi-database queries (such as SHOW DATABASES, CREATE DATABASE, etc.) also now target the “memgraph” database and require access to it. This requirement affects multi-tenant environments where users might have access to other databases but not the default one.

  1. Restrict memgraph database access: Treat the “memgraph” database as a system database and allow only administrators to have access to it
  2. Use tenant-specific databases: Store all application data in dedicated tenant databases
  3. Separate concerns: Keep user management, role management, system administration, replication management, and multi-database management separate from application data

Example configuration

-- Create admin role with full system privileges
CREATE ROLE system_admin;
GRANT ALL PRIVILEGES TO system_admin;
GRANT DATABASE memgraph TO system_admin;
 
-- Create tenant-specific roles (no access to memgraph database)
CREATE ROLE tenant1_admin;
REVOKE DATABASE memgraph FROM tenant1_admin;
CREATE ROLE tenant1_user;
REVOKE DATABASE memgraph FROM tenant1_user;
CREATE ROLE tenant2_admin;
REVOKE DATABASE memgraph FROM tenant2_admin;
CREATE ROLE tenant2_user;
REVOKE DATABASE memgraph FROM tenant2_user;
 
-- Grant appropriate permissions to tenant roles
GRANT MATCH, CREATE, MERGE, SET, DELETE, INDEX TO tenant1_admin;
GRANT CREATE, READ, UPDATE, DELETE ON NODES CONTAINING LABELS * TO tenant1_admin;
GRANT CREATE, READ, UPDATE, DELETE ON EDGES CONTAINING TYPES * TO tenant1_admin;
GRANT MATCH, CREATE, MERGE, SET, DELETE TO tenant1_user;
GRANT CREATE, READ, UPDATE, DELETE ON NODES CONTAINING LABELS * TO tenant1_user;
GRANT CREATE, READ, UPDATE, DELETE ON EDGES CONTAINING TYPES * TO tenant1_user;
GRANT MATCH, CREATE, MERGE, SET, DELETE, INDEX TO tenant2_admin;
GRANT CREATE, READ, UPDATE, DELETE ON NODES CONTAINING LABELS * TO tenant2_admin;
GRANT CREATE, READ, UPDATE, DELETE ON EDGES CONTAINING TYPES * TO tenant2_admin;
GRANT MATCH, CREATE, MERGE, SET, DELETE TO tenant2_user;
GRANT CREATE, READ, UPDATE, DELETE ON NODES CONTAINING LABELS * TO tenant2_user;
GRANT CREATE, READ, UPDATE, DELETE ON EDGES CONTAINING TYPES * TO tenant2_user;
 
-- Grant access only to tenant databases
GRANT DATABASE tenant1_db TO tenant1_admin;
GRANT DATABASE tenant1_db TO tenant1_user;
GRANT DATABASE tenant2_db TO tenant2_admin;
GRANT DATABASE tenant2_db TO tenant2_user;
 
-- Create users
CREATE USER system_admin_user IDENTIFIED BY 'admin_password';
CREATE USER tenant1_admin_user IDENTIFIED BY 't1_admin_pass';
CREATE USER tenant1_regular_user IDENTIFIED BY 't1_user_pass';
CREATE USER tenant2_admin_user IDENTIFIED BY 't2_admin_pass';
CREATE USER tenant2_regular_user IDENTIFIED BY 't2_user_pass';
 
-- Assign roles
SET ROLE FOR system_admin_user TO system_admin;
SET ROLE FOR tenant1_admin_user TO tenant1_admin;
SET ROLE FOR tenant1_regular_user TO tenant1_user;
SET ROLE FOR tenant2_admin_user TO tenant2_admin;
SET ROLE FOR tenant2_regular_user TO tenant2_user;

In this configuration:

  • system_admin_user can perform all authentication/authorization, replication, and multi-database operations and has access to the “memgraph” database
  • Tenant users can only access their respective tenant databases
  • Application data is completely isolated in tenant-specific databases
  • The “memgraph” database serves purely as an administrative database

Isolated databases

Isolated databases within Memgraph function as distinct single-database Memgraph instances. Queries executed on a specific database should operate as if it were the sole database in the system, preventing cross-database contamination. Users interact with individual databases, and cross-database queries are prohibited.

Every database has its own database UUID, which can be read by running the SHOW STORAGE INFO query on a particular database.

Database configuration and data directory

At present, all isolated databases share identical configurations. There is no provision to specify a per-database configuration.

The sole distinction lies in the location of the data directory. The designated data directory serves as the root and retains data associated with the default database. Other databases are housed in new directories within data_directory/databases/*db_name*.

The default memgraph database also includes a directory data_directory/databases/memgraph, which contains symbolic links leading back to the root. Some links are proactively generated and their status may vary based on configuration.

User interface

Cypher queries for multi-tenancy

Users interact with multi-tenant features through specialized Cypher queries:

  1. CREATE DATABASE name: Creates a new database.
  2. DROP DATABASE name [FORCE]: Deletes a specified database.
  3. RENAME DATABASE old_name TO new_name: Renames a database.
  4. SHOW DATABASE: Shows the current used database. It will return NULL if no database is currently in use. You can also use SHOW CURRENT DATABASE for the same functionality. This command does not require any special privileges.
  5. SHOW DATABASES: Shows only the existing set of multitenant databases. The result includes a Name column, a State column (HOT/COLD) and a Health column (ready/broken). HOT databases are resident in memory while COLD are suspended, but still listed. A database is reported as broken when it failed durability recovery and came up empty — see recovery failure handling.
  6. USE DATABASE name: Switches focus to a specific database (disabled during transactions).
  7. GRANT DATABASE name TO user_or_role: Grants a user or role access to a specified database.
  8. DENY DATABASE name FROM user_or_role: Explicitly denies a user or role access to a specified database.
  9. REVOKE DATABASE name FROM user_or_role: Removes the database from the user’s or role’s database access list.
  10. SET MAIN DATABASE name FOR user: Sets a user’s default (landing) database.
  11. SHOW DATABASE PRIVILEGES FOR user: Lists a user’s database access rights.
  12. SUSPEND DATABASE name: Tears a tenant’s in-memory storage down to a durable COLD shell to free RAM, keeping its data on disk. See Suspending and resuming databases.
  13. RESUME DATABASE name: Rebuilds a suspended (COLD) tenant back to HOT with all data intact. See Suspending and resuming databases.

Removing database access: DENY vs REVOKE

There are two ways to remove access to a database: DENY DATABASE x or REVOKE DATABASE x. They behave differently:

  • DENY explicitly bans the user or role from the database. If any role that a user has (or the user itself) is denied access to a database, the user cannot access it. Deny trumps any other access granted—no combination of grants can override a deny.
  • REVOKE removes the database from the user’s or role’s database access list. It does not block access: if the user has other roles (or the user itself has access through another path) that still have access to that database, the user can still use it when connected to that database (tenant).

Use DENY when you need to explicitly forbid access to a database for any user with that role, regardless of their other roles. Use REVOKE when you simply want to remove the default access (like the default “memgraph” database access) or a previously granted access, allowing the user to potentially access the database if another of their roles grants it.

DROP DATABASE with FORCE

The DROP DATABASE command removes an existing database. You can optionally include the FORCE parameter to delete a database even when it has active connections or transactions.

Syntax

DROP DATABASE database_name [FORCE];

Behavior

  • Without FORCE: The command will fail if the database is currently in use by any active connections or transactions.
  • With FORCE: The database will be immediately hidden from new connections, but actual deletion is deferred until it’s safe to proceed. All active transactions using the database will be terminated.

Use cases for FORCE

  • Emergency cleanup: Remove a database stuck in an inconsistent or long-running state.
  • Administrative maintenance: Perform system maintenance requiring immediate database removal.
  • Development environments: Quickly reset test environments that might still have active connections.

Privileges required

Using the FORCE option requires:

  • MULTI_DATABASE_EDIT privilege
  • Access to the memgraph database
  • TRANSACTION_MANAGEMENT privilege (to terminate active transactions)

Important considerations

  • All active transactions on the target database will be forcibly terminated.
  • The database becomes immediately unavailable to new connections.
  • Actual deletion may be deferred until existing connections are properly closed.
  • This operation cannot be undone.

RENAME DATABASE

The RENAME DATABASE command allows you to rename an existing database to a new name. This simplifies administrative workflows by eliminating the need to create a new database, recover from a snapshot, and drop the old database.

Syntax

RENAME DATABASE old_name TO new_name;

Behavior

  • The database is renamed immediately without requiring unique access.
  • If you are currently using the database being renamed, the current database context is automatically updated to the new name.
  • All existing data, indexes, constraints, and other database objects are preserved.

Current implementation of RENAME does not update auth data. User/role database access and database-specific roles information is not updated. This can lead to unindented access to databases.

Important considerations

  • The RENAME DATABASE command requires the MULTI_DATABASE_EDIT privilege and access to the memgraph database.
  • The new database name must not already exist.
  • The old database name must exist.
  • This operation cannot be undone once completed.
  • All active connections to the database will continue to work seamlessly with the new name.

Suspending and resuming databases Enterprise

In a multi-tenant instance, every HOT tenant keeps its full graph in RAM. When most tenants are idle at any given moment, this caps how many tenants fit on a node. Suspending a tenant tears down its in-memory storage — reclaiming that RAM — while leaving a lightweight, durable COLD shell on disk. Resuming rebuilds the tenant HOT from disk with all data intact.

Cold is a memory state, not a data state. Suspending a database never deletes or loses data; it only drops the in-memory copy. The on-disk snapshot and WAL are left untouched, and resuming recovers the tenant to exactly where it was.

Syntax

SUSPEND DATABASE database_name;   -- HOT → COLD, frees RAM
RESUME DATABASE database_name;    -- COLD → HOT, rebuilds from disk

A successful SUSPEND DATABASE mydb returns Successfully suspended database mydb; a successful RESUME DATABASE mydb returns Successfully resumed database mydb. Resuming a database that is already HOT is an idempotent success and returns Database mydb is already resumed (HOT).

Example

-- Free the RAM held by an idle tenant.
SUSPEND DATABASE mydb;
 
-- Confirm it is now COLD (its data is still on disk).
SHOW DATABASES;
-- Name    state
-- memgraph  HOT
-- mydb      COLD
 
-- Bring it back into memory before querying it again.
RESUME DATABASE mydb;
 
-- mydb is HOT again, with all data intact.
USE DATABASE mydb;
MATCH (n) RETURN count(n);

Privileges required

SUSPEND DATABASE and RESUME DATABASE require the MULTI_DATABASE_EDIT privilege and access to the memgraph database — the same requirements as CREATE/DROP/RENAME DATABASE. Both are Enterprise-only; without a valid enterprise license the query is rejected with Access to multi-tenancy requires an enterprise, ai_platform, or oem license.

Requirements and restrictions

A database can be suspended only when all of the following hold:

  • It is not the default memgraph database. Attempting to suspend it fails with Cannot suspend the default database.
  • It uses the in-memory transactional storage mode. On-disk and in-memory analytical databases cannot be suspended (analytical mode suppresses the WAL), and the query fails with Database <name> is not in-memory mode; only in-memory databases can be suspended.
  • Periodic snapshots and WAL are enabled for the database, so a suspended tenant is recoverable. Otherwise the query fails with Database <name> does not have periodic snapshot+WAL durability enabled; cannot suspend safely.
  • No client is using it. Suspend does not terminate in-flight work; it waits briefly for the tenant to become idle and, if connections or transactions are still active, returns the retriable Database <name> has active connections; cannot suspend while in use. Disconnect the clients (or wait for their transactions to finish) and re-issue the query.

Suspending a non-existent or already-suspended database returns Database <name> does not exist or is already cold.

If a resume fails to rebuild the storage (for example, under memory pressure), the tenant is left COLD and the query returns Database <name> failed to recover while resuming; it remains suspended (cold) and the resume can be retried. No data is lost — retry the resume. Resuming a database that is not suspended returns Database <name> does not exist or is not suspended.

Working with a suspended database

A COLD database is not queryable until it is resumed. The behavior of other commands on a suspended tenant is:

  • USE DATABASE <cold> (or the first query on a session pointed at a cold tenant) fails with Database "<name>" is suspended (cold); run RESUME DATABASE <name> before using it. Run RESUME DATABASE first, then use it. (Resume is not automatic on access.)
  • SHOW DATABASES lists the tenant with its state shown as COLD.
  • SHOW STORAGE INFO ON DATABASE <cold> succeeds and returns the tenant’s statistics as of the moment it was suspended (its state field reads COLD). Fields that only exist for a running database — such as query_memory_tracked, vector_index_memory_tracked and tenant_memory_tracked — read 0 B, and tenant_memory_limit reads unlimited. See Server stats.
  • DROP DATABASE <cold> drops the tenant directly, without resuming it; the name becomes immediately reusable.
  • RENAME DATABASE <cold> is rejected with Cannot rename database <old_name>: it is suspended (cold). RESUME it first.
  • Metadata-only commands do not resume the tenant. GRANT/DENY/REVOKE DATABASE, SET MAIN DATABASE, SHOW DATABASES and tenant-profile operations all operate on a cold tenant without bringing it back into memory.

Durability and snapshots

SUSPEND DATABASE does not take a proactive snapshot. Durability at suspend time is whatever the tenant’s periodic snapshot and WAL already provide, plus — if --storage-snapshot-on-exit is enabled — the snapshot the storage writes during its normal teardown. Because RESUME recovers from the latest snapshot plus WAL replay, data is intact either way; enabling --storage-snapshot-on-exit mainly makes the subsequent resume faster by reducing the amount of WAL to replay.

The COLD state is persisted, so suspended databases survive a restart: on recovery a COLD tenant is restored as a durable shell (no RAM is used until you resume it), and HOT tenants are recovered normally.

Replication

SUSPEND/RESUME DATABASE are system-replicated, exactly like CREATE/DROP DATABASE. Issue them on the MAIN; each registered replica applies the same transition and converges to MAIN’s authoritative HOT/COLD set — including replicas that were disconnected, lagging, or restarted while the transition happened. You do not (and cannot) suspend or resume on a replica: these queries are rejected there with Query forbidden on the replica!.

Observability

Suspend/resume activity is exported through Prometheus metrics: memgraph_database_suspends_total, memgraph_database_resumes_total, the memgraph_cold_databases gauge (current number of suspended databases), and the memgraph_database_suspend_latency_seconds / memgraph_database_resume_latency_seconds histograms. See Monitoring.

User’s main database

Administrators assign default databases to users, ensuring a seamless and secure connection experience. Users cannot connect to Memgraph if they lack access rights to their default database. This situation may arise from database deletion or revoked access rights.

User privileges and database access

Authentication and authorization data are shared across databases, providing a unified source of truth. A single user can access multiple databases with a global set of privileges, but currently, per-database privileges cannot be granted.

⚠️

User-role mappings are simple maps located in the user. Deleting or renaming the database will not update this information. The admin needs to make sure the correct access is maintained at all times.

Access to all databases can be granted or revoked using wildcards: GRANT DATABASE * TO user;, DENY DATABASE * FROM user; or REVOKE DATABASE * FROM user;.

Multi-database queries and the memgraph database

As of Memgraph v3.5 multi-database queries (such as SHOW DATABASES, CREATE DATABASE, DROP DATABASE, RENAME DATABASE, etc.) target the “memgraph” database and require access to it.

To execute these queries, users must have:

  • The appropriate privileges (MULTI_DATABASE_USE, MULTI_DATABASE_EDIT)
  • AND access to the default “memgraph” database

Multi-tenant query syntax changes

As of Memgraph v3.5 the syntax for certain queries in multi-tenant environments have changed. The SHOW ROLE and SHOW PRIVILEGES commands now require specifying the database context in some cases.

SHOW ROLE FOR USER: This command does not require database specification and will show all roles assigned to the user across all databases.

SHOW PRIVILEGES FOR USER: This command requires database specification in multi-tenant environments.

SHOW PRIVILEGES FOR ROLE: This command does not require database specification and will show all privileges for the role.

In multi-tenant environments, you must specify which database context to use when showing privileges for users:

  1. Show roles for the user’s main database:
SHOW ROLE FOR user_name ON MAIN;
  1. Show roles for the current database:
SHOW ROLE FOR user_name ON CURRENT;
  1. Show roles for a specific database:
SHOW ROLE FOR user_name ON DATABASE database_name;

SHOW PRIVILEGES syntax in multi-tenant environments

Similarly, the SHOW PRIVILEGES command requires database context specification:

  1. Show privileges for the user’s main database:
SHOW PRIVILEGES FOR user_or_role ON MAIN;
  1. Show privileges for the current database:
SHOW PRIVILEGES FOR user_or_role ON CURRENT;
  1. Show privileges for a specific database:
SHOW PRIVILEGES FOR user_or_role ON DATABASE database_name;

These commands return the aggregated roles and privileges for the user in the specified database context. The ON MAIN option shows information for the user’s main database, ON CURRENT shows information for whatever database is currently active, and ON DATABASE shows information for the explicitly specified database.

Impact on multi-tenant environments

In multi-tenant environments where users might not have access to the “memgraph” database, multi-database management operations will fail. This reinforces the recommendation to treat the “memgraph” database as an administrative/system database.

Example: Admin user with multi-database privileges

-- Create admin role with multi-database privileges
CREATE ROLE multi_db_admin;
GRANT MULTI_DATABASE_USE, MULTI_DATABASE_EDIT TO multi_db_admin;
GRANT DATABASE memgraph TO multi_db_admin;
 
-- Create user with multi-database admin role
CREATE USER db_admin IDENTIFIED BY 'admin_password';
SET ROLE FOR db_admin TO multi_db_admin;

In this setup, db_admin can:

  • Execute all multi-database queries (SHOW DATABASES, CREATE DATABASE, DROP DATABASE, RENAME DATABASE, etc.)
  • Access the “memgraph” database for administrative operations
  • Manage the multi-tenant database configuration

Best practice

For multi-database management, ensure that users who need to perform multi-database operations have both the appropriate multi-database privileges and access to the “memgraph” database. This aligns with the overall recommendation to treat the “memgraph” database as an administrative database in multi-tenant environments.

Additional multi-tenant privileges

Administrators manage multi-tenant privileges with:

  • MULTI_DATABASE_USE: Enables database switching and listing.
  • MULTI_DATABASE_EDIT: Permits database creation and deletion.

Configuration flags

The data-recovery-on-startup flag replaces storage-recover-on-startup, facilitating recovery of individual databases and their contents during startup.

Connecting to a database

The user can interact with multi-tenant databases in two ways:

  1. Through Cypher queries.
  2. When using Neo4j drivers, by defining the database field. The USE DATABASE query is disabled when the database field is defined. All queries run against the specified database only.

When connecting to Memgraph without defining a particular landing database, you will be connected to the default database set for the user. In case the user does not have a default (main) database, a database-less connection will be established. During this connection, the user can execute queries that do not manipulate any data. User can still use multi-tenant queries and define a database to use via the appropriate Cypher query.

Example using Neo4j Python driver:

import neo4j
 
driver = neo4j.GraphDatabase.driver("bolt://localhost:7687", auth=("user", "pass"))
 
with driver.session() as session:
    session.run(...)  # Executes on the default database
    session.run("USE DATABASE db1")
    session.run(...)  # Executes on db1
 
with driver.session(database="db2") as session:
    session.run(...)  # Executes on db2
    session.run("USE DATABASE db1")  # Error: database switching disabled

Audit Logs

Audit logs now encompass the active database name, positioned immediately after the username field.

Backwards compatibility

The multi-tenant feature ensures backwards compatibility, facilitating smooth version upgrades and downgrades without disrupting user experience. During an upgrade, previous data is migrated to the default database, while downgrading retains data solely in the default database.

For detailed upgrade procedures — including high-availability clusters and rolling upgrades — see the Upgrades page and the version-specific guides.