-
Notifications
You must be signed in to change notification settings - Fork 0
Sanitization Strategies
DBMigrator supports seven sanitization strategies. Each strategy generates a SQL UPDATE statement applied to the target database after the dump is restored.
Sanitization runs per-table, not per-row — it uses a single UPDATE statement, which is efficient even on large tables.
All sanitization rules execute inside a single database transaction. If any rule fails (e.g., a column doesn't exist, a type mismatch, or a NOT NULL violation), the entire transaction is rolled back and the target database is left unchanged. There is no partial sanitization state.
In --dry-run mode the transaction is always rolled back after printing the SQL, so no data is modified.
Replaces all values in the column with a fixed string.
- name: "password_hash"
strategy: "static"
value: "$2b$10$REDACTED_HASH_VALUE_HERE"Use when: you want all rows to share a known test value (e.g., a universal test password).
Sets the column to NULL.
- name: "avatar_url"
strategy: "null_value"Requirements: the column must be nullable. The validate command will report an error if you apply this to a NOT NULL column.
Use when: the data is sensitive but optional and not needed in development.
Generates values from a template string using column references. References are resolved as SQL concatenation at query time.
- name: "email"
strategy: "template"
value: "user_{id}@redacted.local"The {id} placeholder is replaced by the actual id column value per row, producing unique values like user_42@redacted.local.
You can combine multiple column references:
value: "{first_name}_{last_name}_{id}@test.local"Use when: you need deterministic, unique values that still look realistic and traceable (e.g., emails that include the original ID).
Generates realistic but fake data using the Bogus library. A new value is generated per row.
- name: "first_name"
strategy: "faker"
faker: "first_name"
- name: "email"
strategy: "faker"
faker: "email"See Faker Methods Reference for all 23+ available methods.
Use when: you need realistic-looking data in the target environment (e.g., for UI testing or demos).
Note: By default faker values differ on every run. Set
faker_seedin your config to a fixed integer to make output reproducible across runs. Referential integrity across tables is still not preserved regardless of seed — usehashwhen FK consistency matters.
Replaces the value with its SHA256 hex digest. The same input always produces the same output.
- name: "national_id"
strategy: "hash"
- name: "user_ref"
strategy: "hash"Use when: you need to pseudonymize data while preserving uniqueness and foreign key relationships across tables.
Keeps a configurable number of leading and/or trailing characters visible and replaces the middle with a mask character (default *). The total string length is preserved.
# Keep last 4 digits: "+1 555 123 4567" → "***********4567"
- name: "phone"
strategy: "partial_mask"
keep_last: 4
# Keep first 2 and last 4: "john.doe@example.com" → "jo**************com"
- name: "email"
strategy: "partial_mask"
keep_first: 2
keep_last: 3
mask_char: "*" # optional, default: *| Field | Required | Description |
|---|---|---|
keep_first |
One of the two must be set | Number of leading characters to keep visible |
keep_last |
One of the two must be set | Number of trailing characters to keep visible |
mask_char |
No | Single character used to fill the masked portion. Default: *
|
The expression is generated as pure SQL (LEFT + REPEAT + RIGHT) — values are never read into application memory.
Use when: you need to comply with PII masking policies while keeping enough context for support or debugging (e.g., last 4 digits of a phone number).
Picks a random value from a user-defined list on each row. Useful for categorical fields like status, role, country_code, or plan.
- name: "status"
strategy: "random_from"
values: ["active", "inactive", "pending"]
- name: "country_code"
strategy: "random_from"
values: ["US", "ES", "MX", "AR", "CO"]| Field | Required | Description |
|---|---|---|
values |
Yes | List of at least 2 strings to pick from |
The selection is done in SQL using ARRAY[...][floor(random() * N)::int + 1] — no data is read into the application.
Use when: a column holds a known set of categorical values and you want the sanitized data to look realistic within that domain.
All strategies support an optional where clause that limits which rows are updated:
- table: "users"
where: "role != 'admin'"
columns:
- name: "email"
strategy: "faker"
faker: "email"This is useful to preserve certain rows (e.g., admin accounts, seed data) while redacting the rest.
| Strategy | Uniqueness | Referential Integrity | Realistic | Deterministic |
|---|---|---|---|---|
static |
No | No | No | Yes |
null_value |
No | No | N/A | Yes |
template |
Yes (if using ID) | Yes | Partial | Yes |
faker |
Mostly | No | Yes | With faker_seed
|
hash |
Yes | Yes | No | Yes |
partial_mask |
Preserves original | Preserves original | Yes | Yes |
random_from |
No | No | Yes (categorical) | No |