# Top Dynamic Data Masking Tools in 2026

> Dynamic data masking tools compared: native in Oracle, SQL Server, Snowflake, BigQuery, MySQL, an extension for Postgres, plus cross-database platforms.

Adela | 2026-07-28 | Source: https://www.bytebase.com/blog/top-dynamic-data-masking-tools/

---

> **Note:** This post is maintained by Bytebase, an open-source database governance platform. We update the post periodically.

Dynamic data masking (DDM) rewrites sensitive values at read time, so the stored data never changes and what each user sees depends on who they are. Shopping for it splits along one line that decides most of the rest: mask inside the engine, or mask on the path in front of it. Engine-native masking is free with the license you already pay for and stops at that engine's boundary. A cross-database layer costs money and covers the fleet. Which side you land on usually comes down to how many engines you run, and whether anyone will ask you to prove the policy.

What are the criteria? Every pick here is:

- **Read-time only** - tools that permanently rewrite a copy are static masking, a different control. See [static data masking tools](/blog/static-data-masking-tools/) for that side.
- **Actively maintained** - verified as of July 2026, with the version or edition that carries the feature named.
- **Adoptable on its own** - no pick requires re-platforming your data stack first.

## Masking in the engine

### Oracle Data Redaction

[Oracle Data Redaction](https://docs.oracle.com/en/database/oracle/oracle-database/19/asoag/introduction-to-oracle-data-redaction.html) is the most complete native implementation of the group. Policies are defined with `DBMS_REDACT`, evaluated per session, and support full, partial, random, and regular-expression redaction.

**Licensing:** part of the Advanced Security option, which is a paid add-on to Enterprise Edition. Not available on Standard Edition.

**Best for:** Oracle shops that already bought Advanced Security. If you have not, price the option before designing around it.

Depth on the policy syntax lives in [Oracle dynamic data masking](/blog/oracle-dynamic-data-masking/).

### SQL Server Dynamic Data Masking

[SQL Server DDM](https://learn.microsoft.com/en-us/sql/relational-databases/security/dynamic-data-masking) ships in every edition since SQL Server 2016 and in Azure SQL Database. Masks are declared on the column with `ALTER TABLE ... ALTER COLUMN ... ADD MASKED WITH (FUNCTION = '...')`, which makes it the fastest of these to turn on.

The catch is documented by Microsoft itself and still current in 2026: DDM is obfuscation, not a security boundary. A user with query rights can recover values byte by byte through inference, because predicates run against the real data. `WHERE ssn LIKE '123%'` returns rows or does not, and that answer leaks the value without ever unmasking a cell. Pair it with row-level security or restricted query surfaces.

**Licensing:** included in all editions, including Express.

**Best for:** reducing casual exposure in internal tools. Not for adversarial users.

More in [SQL Server dynamic data masking](/blog/sql-server-dynamic-data-masking/).

### Snowflake masking policies

Snowflake masking policies are schema-level objects attached to columns, with the policy body written as a `CASE` expression over `CURRENT_ROLE()`. Conditional masking on another column's value is supported, which most engine-native implementations do not offer.

One operational detail to plan around: the unmask audit trail lives in `ACCESS_HISTORY`, which lags by one to two hours. Real-time alerting on masked-column access needs something else in the path.

**Licensing:** Enterprise Edition and above.

**Best for:** teams already standardized on Snowflake, especially with policies managed through Terraform. The known limits are collected in [Snowflake dynamic data masking and alternatives](/blog/snowflake-dynamic-data-masking-and-alternatives/).

### BigQuery data masking

[BigQuery](https://cloud.google.com/bigquery/docs/column-data-masking-intro) masks through Data Catalog: build a taxonomy of policy tags, attach a tag to a column, then bind a masking rule and a set of principals to that tag with a data policy. At read time, anyone without the Masked Reader (or Fine-Grained Reader) role gets the masked value; the stored data never changes.

The setup is heavier than a single DDL statement, and there is no SQL or `bq` command for the data-policy step, only the Data Policy API or Terraform. In exchange, BigQuery does not gate the feature behind a paid edition the way Snowflake does: masking is GA with no separate license charge.

**Licensing:** free, included with every BigQuery project.

**Best for:** GCP-standardized teams already using Data Catalog taxonomies, or anyone put off by Snowflake's Enterprise-only gate.

More in [BigQuery dynamic data masking](/blog/bigquery-dynamic-data-masking/).

### MySQL 9.7 Enterprise

Dynamic data masking is GA in **MySQL 9.7 Enterprise Edition** and OCI MySQL HeatWave. `CREATE MASKING POLICY` defines the rule, `ALTER TABLE ... ALTER COLUMN ... SET MASKING POLICY` attaches it to a specific column, and the server enforces it on every read path, including `mysqldump`. That last part matters: the pre-9.7 pattern wrapped base tables in views, and anyone with `SELECT` on the base table walked straight past it.

**Licensing:** Enterprise Edition and HeatWave only. Community Edition has neither the policy object nor the masking functions.

_Alternatives:_ Percona Data Masking ships the same function library free with Percona Server, but as of 9.7 it has not implemented `CREATE MASKING POLICY`, so the open-source path is still views over functions. MariaDB MaxScale has a masking filter that works at the proxy layer.

Full syntax and the account-model gotchas are in [MySQL dynamic data masking](/blog/mysql-dynamic-data-masking/).

### PostgreSQL Anonymizer

PostgreSQL has no native DDM. [PostgreSQL Anonymizer](https://postgresql-anonymizer.readthedocs.io/) by Dalibo is the mature answer: masking rules declared as security labels in DDL, with substitution, randomization, faking, pseudonymization, partial scrambling, shuffling, noise, and generalization. Version 3.0 landed in February 2026, adding parallel static masking and JSON import/export, and it now requires PostgreSQL 14 or later.

**Licensing:** PostgreSQL License (BSD-style). Free.

**The practical limit:** it is an extension, and installing it needs privileges that most managed Postgres services do not grant. Check your provider's extension allowlist before planning around it. Teams on RDS or Cloud SQL usually end up masking in a layer above instead.

More in [Postgres dynamic data masking](/blog/postgres-dynamic-data-masking/).

## Masking in front of the engine

### Immuta

[Immuta](https://www.immuta.com/) applies policy at query runtime across Snowflake, Databricks, BigQuery, Redshift, and Starburst, with attribute-based access control and automated sensitive-data discovery. Policies are authored once and pushed into each platform.

**Licensing:** enterprise sales only, no published pricing. Third-party listings put mid-market contracts in the six-figure range annually, so treat it as a platform purchase rather than a tool.

**Best for:** analytics estates with many consumers and a compliance function that wants one policy catalog.

_Alternatives:_ Privacera, built on Apache Ranger, covers structured and unstructured sources and pushes policies into the native service. Satori sits in the connection path instead, which shortens deployment at the cost of adding a hop.

### Bytebase

[Bytebase](https://docs.bytebase.com/security/data-masking/overview/) masks query results on the path, with one policy set across every supported engine. Policies come from three levels: global rules by semantic type, column-level overrides, and per-user exemptions, evaluated in that order. Masking propagates to dependent views automatically, so a masked column stays masked in anything derived from it.

**Licensing:** Enterprise plan. Community (free, up to 20 users) and Pro ($20/user/month) do not include masking.

**The honest limit:** masking applies to queries that go through Bytebase. An application connecting directly to the database with its own credentials is outside that path, so this fits human and AI-agent access rather than application traffic. If you need masking for the app tier too, that is an engine-native job.

**Best for:** multiple engines, where the alternative is maintaining five different policy dialects and no single audit trail.

## Comparison

| Tool | Engines | Policy defined in | Audit | License |
| --- | --- | --- | --- | --- |
| Oracle Data Redaction | Oracle | `DBMS_REDACT` | Unified audit | Advanced Security add-on |
| SQL Server DDM | SQL Server, Azure SQL | Column DDL | Manual | All editions |
| Snowflake policies | Snowflake | Policy object | `ACCESS_HISTORY` (1-2h lag) | Enterprise Edition+ |
| BigQuery masking | BigQuery | Policy tags | Cloud Audit Logs | Free, all editions |
| MySQL 9.7 Enterprise | MySQL | `CREATE MASKING POLICY` | Enterprise audit plugin | Enterprise / HeatWave |
| PostgreSQL Anonymizer | Postgres | Security labels in DDL | None built in | PostgreSQL License (free) |
| Immuta | Snowflake, Databricks, BigQuery, Redshift, Starburst | Central policy catalog | Built in | Commercial, six figures |
| Bytebase | 20+ engines | Global rules + column overrides | Built in | Enterprise plan |

## Picking one

If you run one engine, use its native masking and stop reading. Oracle and Snowflake both have implementations good enough that adding a layer buys you little, and the money is better spent elsewhere.

Three situations change that answer. The first is Postgres or MySQL Community, where native masking either does not exist or is locked behind an edition you do not have. The second is more than two engines, at which point you are writing the same policy in three dialects and reconciling three audit formats by hand. The third is a compliance ask, where "show me every masking policy and who was exempted last quarter" needs to be one report rather than a week of screenshots.

One thing worth settling before you compare features: whether you also need [static masking](/blog/static-vs-dynamic-data-masking/) for non-production copies. The two controls solve different problems and most teams eventually run both. For the implementation order and the mistakes that show up in production, see [dynamic data masking best practices](/blog/dynamic-data-masking-best-practices/).

## Related reading

- [What is Dynamic Data Masking (DDM)](https://www.bytebase.com/blog/what-is-dynamic-data-masking/)
- [Dynamic Data Masking Best Practices](https://www.bytebase.com/blog/dynamic-data-masking-best-practices/)
- [Static Data Masking Tools (and How to Roll Your Own)](https://www.bytebase.com/blog/static-data-masking-tools/)
- [Static vs Dynamic Data Masking: When to Use Which](https://www.bytebase.com/blog/static-vs-dynamic-data-masking/)