# Snowflake Dynamic Data Masking (DDM) and Alternatives

> Compare Snowflake Dynamic Data Masking with database views and Bytebase fleet-wide masking — edition gate, policy management, audit trail.

Tianzhou | 2025-09-24 | Source: https://www.bytebase.com/blog/snowflake-dynamic-data-masking-and-alternatives/

---

## Snowflake Dynamic Data Masking

Snowflake Dynamic Data Masking (DDM) rewrites query results for unauthorized roles. Cleartext stays in the table. A role-based predicate decides what reaches the user. Policies are defined per column, evaluated at read time.

A simple masking policy in Snowflake:

```sql
-- Create a masking policy for email addresses
CREATE OR REPLACE MASKING POLICY email_mask AS (val STRING)
RETURNS STRING ->
  CASE
    WHEN CURRENT_ROLE() IN ('ADMIN', 'DATA_ANALYST') THEN val
    ELSE REGEXP_REPLACE(val, '.+@', '*****@')
  END;

-- Apply the masking policy to a column
ALTER TABLE customers
MODIFY COLUMN email SET MASKING POLICY email_mask;
```

## Limitations

Snowflake DDM has documented gaps:

### 1. Edition gate and cost

Snowflake DDM is part of Column-level security. Gated behind **Enterprise edition** or **Business Critical**. Standard has none. Pricing implication:

| Edition           | Price per Credit | Cost Increase | DDM Available |
| ----------------- | ---------------- | ------------- | ------------- |
| Standard          | $2               | -             | ❌            |
| Enterprise        | $3               | +50%          | ✅            |
| Business Critical | $4               | +100%         | ✅            |

Standard-edition fleets pay a **50% per-credit increase** to enable DDM. The increase applies to every workload, not just masked queries.

### 2. Policy management at scale

DDM at scale runs into three operational gaps. Policies proliferate — one per sensitive column, no aggregation. Snowsight ships no DDM UI; every policy lives in SQL. Policy edits and exemption grants have no built-in audit trail.

```sql
-- Example of policy complexity with multiple roles and conditions
CREATE OR REPLACE MASKING POLICY customer_pii_mask AS (val STRING)
RETURNS STRING ->
  CASE
    WHEN CURRENT_ROLE() = 'DATA_OWNER' THEN val
    WHEN CURRENT_ROLE() = 'ANALYST_SENIOR' AND
         CURRENT_WAREHOUSE() = 'ANALYTICS_WH' THEN val
    WHEN CURRENT_ROLE() = 'CUSTOMER_SERVICE' AND
         CURRENT_TIME() BETWEEN '09:00'::TIME AND '17:00'::TIME THEN
         CONCAT(LEFT(val, 3), '***', RIGHT(val, 2))
    WHEN CURRENT_ROLE() IN ('ANALYST_JUNIOR', 'INTERN') THEN '***MASKED***'
    ELSE NULL
  END;
```

## Alternatives to Snowflake Dynamic Data Masking

Two alternatives sidestep the edition gate:

### 1. Database Views

Database views deliver masking on Standard edition. A view wraps the base table; grant access to the view, not the table. Role-based logic and masking functions live inside the view's `SELECT`.

```sql
-- Create a masked view for customer data
CREATE OR REPLACE VIEW customers_masked AS
SELECT
    customer_id,
    customer_name,
    CASE
        WHEN CURRENT_ROLE() IN ('ADMIN', 'DATA_ANALYST')
        THEN email
        ELSE REGEXP_REPLACE(email, '.+@', '*****@')
    END AS email,
    CASE
        WHEN CURRENT_ROLE() = 'FINANCE_ADMIN'
        THEN credit_card_number
        WHEN CURRENT_ROLE() = 'CUSTOMER_SERVICE'
        THEN CONCAT('****-****-****-', RIGHT(credit_card_number, 4))
        ELSE '****-****-****-****'
    END AS credit_card_number,
    registration_date
FROM customers;
```

- **Pros.** No edition gate. Works on Standard.
- **Cons.** View proliferation grows with every variation. No enforcement — anyone with `SELECT` on the base table sees cleartext.

### 2. Bytebase

Snowflake gates DDM behind Enterprise (+50% per credit) or Business Critical (+100%). Standard has none. [Bytebase Dynamic Data Masking](https://docs.bytebase.com/security/data-masking/overview) applies the same masking model on Standard or Enterprise — without the edition upgrade.

![masking-overview](/content/blog/snowflake-dynamic-data-masking-and-alternatives/masking-overview.webp)

**The mechanism.** Queries route through Bytebase's SQL Editor. Bytebase masks the result before returning it to the user. Snowflake's `MASKING POLICY` objects are not used. Nothing changes inside the warehouse. Policies are managed in a web UI, via Terraform, or via REST API.

![masking-configuration](/content/blog/snowflake-dynamic-data-masking-and-alternatives/masking-configuration.webp)

**The policy model.** Three layers, fixed precedence: **Masking Exemption > Global Masking Rule > Column Masking**.

- **Global Masking Rule.** Workspace-level. Rules evaluate top-down. First match wins. Match conditions span environment, project, database, and data classification. One rule covers every Snowflake account in the fleet — plus the Postgres and MySQL clusters next to it.
- **Column Masking.** Project-level override on a specific column when the global rule does not apply.
- **Masking Exemption.** Named users receive time-bound `Query` or `Export` exemptions. Service accounts are not eligible. Every grant logged. Every access logged.

**The workflow.** **Request. Review. Approve.** Exemption requests, policy edits, and grant decisions are first-class audit events — recorded alongside the SQL execution itself.

![sql-editor](/content/blog/snowflake-dynamic-data-masking-and-alternatives/sql-editor-masking.webp)

**Enforcement boundary.** Masking applies only to queries routed through the SQL Editor. Service accounts and direct connections to Snowflake — BI tools, application code, scheduled jobs — bypass Bytebase. Bytebase covers the human query path, not service-to-warehouse traffic. Native DDM remains the right tool where service accounts must also be governed.

**Where Bytebase fits:**

- Standard-edition fleets that can't justify the +50% Enterprise upgrade for masking alone.
- Multi-engine fleets where Snowflake sits alongside Postgres, MySQL, or SQL Server. One policy model. Every engine.
- Teams that need approval workflow and audit trail over query access — which native DDM does not provide on top of its column rewrite.

## Comparison

| Solution       | Cost                            | Operational Complexity         | Human Access | Service Access |
| -------------- | ------------------------------- | ------------------------------ | ------------ | -------------- |
| Snowflake DDM  | High (+50% for Enterprise)      | High (SQL-only, no UI)         | Enforced     | Enforced       |
| Database Views | None                            | Very High (View proliferation) | Enforced     | Enforced       |
| Bytebase       | Low (10% of Enterprise edition) | Medium (UI + API/Terraform)    | Enforced     | Not enforced   |

Snowflake DDM covers every access path, at the cost of an Enterprise upgrade. Bytebase covers the human query path at a fraction of that cost — and extends the same model across Postgres, MySQL, and SQL Server alongside Snowflake. On Standard, with a multi-engine fleet, or where approval workflow matters, Bytebase complements native DDM rather than replacing it.