Data masking in Redshift hides sensitive column values from unauthorized users by applying a masking policy.
Redshift data masking lets you obfuscate sensitive values—such as email or credit-card numbers—while still allowing queries to run. Users with the right role see clear text; everyone else sees the masked result.
Create a policy whenever personal or financial information appears in queryable tables and only a subset of users should read the raw data. Policies are reusable and can be attached to many columns.
Use CREATE MASKING POLICY
. You define a return expression that replaces the original value when the current user lacks the required role.
CREATE MASKING POLICY email_mask
WITH (val varchar) AS
CASE
WHEN has_role('pii_access') THEN val
ELSE regexp_replace(val,'^([^@]{3}).*@', '\1***@example.com')
END;
Alter the column and attach the policy with SET MASKING POLICY
. Redshift enforces the policy immediately.
ALTER TABLE customers
ALTER COLUMN email SET MASKING POLICY email_mask;
Query SVV_COLUMN_PRIVILEGES
or inspect DDL via SHOW TABLE
. Masked columns display the policy name.
Use ALTER COLUMN ... UNSET MASKING POLICY
to detach, then DROP MASKING POLICY
if no longer referenced.
Missing role check: Always call has_role()
; otherwise everyone sees masked data, even admins. Fix: Include a role gate in every policy.
Implicit casts: Forgetting to CAST inside policy can raise data-type errors. Fix: Cast masked value to the same column type.
CREATE MASKING POLICY name WITH (val datatype) AS expression;
ALTER TABLE table ALTER COLUMN col SET | UNSET MASKING POLICY name;
DROP MASKING POLICY name;
Yes. One policy can be attached to any column with a matching data type across any schema.
Minimal. Redshift rewrites the query to apply the expression, adding negligible overhead compared to I/O.
Absolutely. Policies work alongside RLS to offer column and row protection simultaneously.