العربيةworlber.sa
Flag of Saudi ArabiaSaudi company · Riyadh

PostgreSQL

Your test database is a copy of production, and that is the problem

Production data ends up in dev and test databases. Here is how masking works in CYBERTEC PGEE, and where it fits in a release pipeline.

12 Oct 2026 · 4 min read

Most teams restore a production dump onto a test server long before anyone reviews what is inside it.

That copy is the real problem. Production sits behind change control, network rules, and a DBA who knows who is connected. The copy sits on a VM in a lower environment, wired to an application server a contractor can reach, and it holds the same customer rows as production.

Masking is the control that fixes the copy instead of the source. In CYBERTEC's PostgreSQL Enterprise Edition (PGEE), masking is part of the database, and the configuration is short enough to sit inside a release pipeline. Here is how it works and where it stops helping.

Masking applies to the export, not to production

PGEE keeps the original values in production. Masking applies to exports: the dump you build for development or test carries transformed values, and the production tables stay as they are.

That distinction tells you what the control covers. Masking protects the copies. It does not shrink the attack surface of the production database, and it is a different control from Transparent Data Encryption, which covers data at rest. If you expected masking to make production safer, you are holding the wrong tool. If you keep shipping unmasked copies to developers, you are holding the right one and have not switched it on.

Defining a mask per column

A mask is attached to a column:

```sql

ALTER TABLE t_product ALTER COLUMN product_number

SET MASK md5(product_number);

```

The mask is an expression, so the transformation can be arithmetic as easily as a hash:

```sql

ALTER TABLE t_product ALTER COLUMN units_available

SET MASK units_available * pi();

```

One rule limits what you can write: only immutable functions are accepted. A volatile function, such as one that reads the clock or pulls a value from a sequence, is rejected.

The constraint has a practical benefit. An immutable function returns the same output for the same input every time, so a customer identifier masked in one table holds the same masked value in every other table. Joins survive the mask, which is usually the reason the test environment is a copy in the first place.

It also carries a limit worth understanding. A deterministic mask is still a hash. Anyone holding the masked copy can hash a guessed value and compare, so a mask over a small or guessable input space is weaker than it looks. That property belongs to deterministic masking in general, not to one implementation.

The arithmetic example is worth reading twice as well. Multiplying units by pi transforms the values rather than hiding them, so the numbers stay plausible and a report built on them will not match production. That is fine for a schema test and wrong for a report test.

Masked dumps

The dump tool takes a flag:

```sql

pg_dump --masked pgee

```

That flag is the control point. A copy made through the masked path carries transformed values. A copy made the way people have always made it carries the original ones. Nothing enforces the flag on your behalf, which is why the change belongs in the copy script rather than in a wiki page.

Masked replication, for environments that stay live

Some test databases are not restores. They are subscribers kept close to production. Plain replication reproduces the source rows:

```sql

CREATE PUBLICATION mypublication_plain FOR TABLE t_product;

```

Masked replication applies the column masks on the way out:

```sql

CREATE PUBLICATION mypublication_masked

FOR TABLE t_product WITH (mask = on);

```

A subscriber fed by the masked publication holds masked data for the same tables and stays current without a nightly dump and restore. For a staging environment that has to look like production, that shape is more useful than a restore.

Where masking does not help

Production keeps its real values by design, so masking does not reduce exposure there.

Masking is not encryption at rest.

Masking does not repair access control on the copy. A masked copy still needs its own credentials, its own network rules, and an owner.

A column added to the schema later arrives without a mask until someone writes one. New columns are the most common route back to unmasked data.

The behaviour described here comes from Worlber's technical documentation for CYBERTEC PGEE and should be confirmed against the release you run, since feature availability can differ between versions.

Putting masking into the release pipeline

  1. List the tables that get copied, and the columns inside them.

  2. Classify each column: keep, mask, or drop before the copy is made.

  3. Write masks using immutable functions only.

  4. Move the copy step onto the masked path so the default copy is a masked one.

  5. Run the test suite against the masked copy and repair the tests that depended on real values.

  6. Reopen the column list whenever the schema changes.

Step five is the one teams skip. A test suite that quietly depended on a customer name matching a fixture will fail on the first masked run, and that failure is the audit working as intended.

Worlber's role

PGEE is CYBERTEC's enterprise PostgreSQL edition. Worlber provides CYBERTEC's enterprise PostgreSQL products and services as a partner offering.

The engineering effort in a masking project is smaller than the classification effort. A payment schema with a few hundred columns needs decisions about which of them are sensitive, which the test suite genuinely uses, and who signs off on the rest. Worlber's PostgreSQL consulting work covers that part of the assessment, and the masking controls sit inside the PGEE deployment itself.

If you already run a copy pipeline and you are not sure which columns in it would need a mask, that inventory is the place to start.

Talk to Worlber

Worlber provides CYBERTEC's enterprise PostgreSQL products and services as a partner offering. If you want to review whether PGEE masking fits your development and test workflow, we can walk through your environment with you.

Talk to Worlber

Next step

Bring us your database challenge

Send us your environment and goal. We will tell you what fits, what does not, and the safest next step.

contactus@worlber.com

Your test database is a copy of production, and that is the problem | Worlber Insights