Course contentsShow
← Data Engineering
Lesson 309 of 8254. Modern Data Warehousing and LakehousesFree lesson

Managing Row-Level Security and Column Masking

Learners will implement row-level filtering and column-level masking techniques to protect PII while maintaining utility for authorized analytical workloads.

In this lesson, you will learn how to restrict data visibility at the granular level by applying row-level filters and column-level masking to protect sensitive information.

When building modern data platforms, we often have diverse personas accessing the same tables. A data scientist might need to analyze purchase trends, but they shouldn’t necessarily see the specific names or addresses of customers. Instead of creating physical copies of tables for every user role, we use Row-Level Security (RLS) and Column Masking to apply rules dynamically at query time.

Row-Level Security (RLS)

RLS acts as a dynamic filter applied to your SELECT statements based on the user's identity. Think of it as an invisible WHERE clause automatically appended to every query. For example, if a regional manager queries the sales table, the engine ensures they only see rows where the region_id matches their own, even if their query lacks a filter.

Column-Level Masking

While RLS controls which rows are visible, Column Masking controls how the data in those rows appears. This is essential for PII (Personally Identifiable Information) like emails or social security numbers. Instead of returning raw data, the system returns a redacted version—such as XXX-XX-1234—to unauthorized users, while returning the full value to authorized administrators.

Here is a conceptual example of how you might define a policy in your metadata layer:

-- Applying a mask to an email column
CREATE MASKING POLICY email_mask AS (val STRING) ->
  CASE 
    WHEN current_user_role() = 'ANALYST' THEN '***@hidden.com'
    ELSE val 
  END;

-- Applying an RLS filter
CREATE ROW ACCESS POLICY region_filter AS (region_id INT) ->
  current_user_role() = 'ADMIN' OR region_id = get_user_region();

By decoupling security logic from the underlying storage, you ensure that analytical utility is maintained—users can still aggregate and compute trends—without exposing sensitive raw values or unauthorized records. This approach keeps your governance centralized and consistent across your entire distributed architecture.

Key Takeaway: Row-level security limits access to specific records based on the user's role, while column masking obscures sensitive values, ensuring compliance without sacrificing the ability to perform complex analysis on the remaining dataset.