Test Data under GDPR
bankingNovember 6, 2026

Test Data under GDPR

Synthetic generation vs. masking production data

Every banking test environment needs data that behaves like the real thing: customers with several accounts, loans with repayment schedules, cards linked to the right accounts, transaction histories that add up to the balance. The fastest way to get that data has always been to copy production. Under GDPR, and now under DORA, that shortcut is a regulated decision. A production copy in a test environment is personal data processed for a new purpose, often with weaker access controls, more people with access and longer retention than the live system. 

Banks usually choose between two alternatives: masking a copy of production data, or generating synthetic data from scratch. Both can produce realistic test data, and both have weaknesses that only become visible in a regulatory review or a missed defect. This article compares them on the dimensions that matter most for banking: realism, referential integrity, edge cases and regulatory risk. It ends with the combined approach we recommend. 


The regulatory starting point 


Three points frame the decision. 

Production data in test is further processing. Customer data was collected to provide banking services, not to test software. Using it for testing has to be compatible with the original purpose (GDPR Article 5(1)(b) and Article 6(4)), limited to what is necessary (data minimisation, Article 5(1)(c)) and protected by design (Article 25). In practice, that means a documented assessment, often a data protection impact assessment, before production data reaches any test environment. 

Masked data is usually still personal data. GDPR distinguishes pseudonymised data, which can still be linked to a person with additional information, from anonymous data, which can't. Pseudonymised data remains personal data and stays fully within GDPR. Most masking produces pseudonymised data, not anonymous data, especially when the bank still holds the originals and the masking rules. True anonymisation is a high bar, as the European data protection authorities' guidance on anonymisation and the EDPB's 2025 guidelines on pseudonymisation both make clear. 

DORA now sets an explicit rule for test environments. The regulatory technical standards on ICT risk management (Commission Delegated Regulation (EU) 2024/1774, Article 16(5) and (6)) require that non-production environments only store anonymised, pseudonymised or randomised production data. Real production data may be used only for specific testing occasions, for limited periods, with approval from the relevant function and reporting to the ICT risk management function. Unmasked production copies sitting in test environments are no longer a grey area for banks. 


Approach 1: masking production data 

Masking takes a copy of production and transforms the fields that identify people, while keeping the structure, volumes and statistical patterns of the real data. Common techniques include: 

Substitution: replacing names, addresses, emails and phone numbers with realistic but fictitious values. 

Deterministic tokenisation: replacing identifiers such as customer numbers, IBANs and national identification numbers with tokens that are always the same for the same input, so relationships survive. 

Format-preserving masking: keeping the format and validity of a value, for example an IBAN with correct check digits, so validation rules still pass. 

Generalisation: reducing precision, such as replacing a date of birth with the year, or a full address with the county. 

Perturbation: adding small random changes to amounts or dates where exact values could identify someone. 


Where masking is strong 

Realism. Masked data keeps the real distributions: how many customers have three accounts, how often loans fall into arrears, what a month-end transaction peak looks like. That matters for performance testing, for analytics and reporting tests, and for migration rehearsals, where the goal is to prove that the real estate migrates correctly. 

Historical edge cases. Production contains decades of data that nobody would think to generate: accounts opened under products withdrawn years ago, legacy status codes, names with unusual characters, records created before a validation rule existed. These are exactly the cases that break migrations and new features, and masked production keeps them. 

Referential integrity, if done consistently. When the same deterministic masking key is used for every system, a customer masked in the core banking system gets the same token in the card system, the CRM and the data warehouse. Cross-system tests keep working. 


Where masking is weak 

Re-identification risk. Removing names and identifiers is not enough. People can often be recognised from combinations of other attributes, called quasi-identifiers: date of birth, town and gender together, an unusually large transfer, a salary from a small employer or a pattern of regular payments. In banking, the hardest fields are free text: payment references, complaint notes and adviser comments regularly contain names, addresses and health or family details. Unless free text is removed or replaced, a masked dataset can still reveal a lot about real people. 

It stays personal data. Because masked data is usually pseudonymised, the test environment holding it needs GDPR-level controls: access management, logging, retention limits and a lawful basis. Every copy, extract and spreadsheet derived from it carries the same obligations. 

Pipelines need maintenance. Each schema change in a source system can introduce a new field that contains personal data. If the masking rules aren't updated, it flows into test unmasked. Masking needs ownership and a review whenever data models change. 

It contains only what production contains. A new product, a new regulatory rule or a scenario that has never happened yet has no examples in production data. 


Keeping referential integrity: a short example 


Deterministic masking is what keeps masked data usable across systems. A keyed hash (HMAC) gives the same output for the same input and key, without allowing the original to be recovered from the output alone. For IBANs, the masked value also needs valid check digits, or every validation rule in the payment flow will reject it: 


 1 public final class DeterministicMasker { 
 2  
 3     private final Mac hmac; 
 4  
 5     public DeterministicMasker(byte[] secretKey) throws GeneralSecurityException { 
 6         this.hmac = Mac.getInstance("HmacSHA256"); 
 7         this.hmac.init(new SecretKeySpec(secretKey, "HmacSHA256")); 
 8     } 
 9  
10     /** Same input and key always give the same token, in every system. */ 
11     public synchronized String token(String value) { 
12         byte[] digest = hmac.doFinal(value.getBytes(StandardCharsets.UTF_8)); 
13         return HexFormat.of().formatHex(digest, 0, 12); 
14     } 
15  
16     /** Masks a Romanian IBAN, keeping country and bank code, with valid check digits. */ 
17     public synchronized String maskIban(String iban) { 
18         String country = iban.substring(0, 2); 
19         String bankCode = iban.substring(4, 8); 
20         byte[] digest = hmac.doFinal(iban.getBytes(StandardCharsets.UTF_8)); 
21         StringBuilder account = new StringBuilder(); 
22         for (int i = 0; account.length() < iban.length() - 8; i++) { 
23             account.append(Math.floorMod(digest[i], 10)); 
24         } 
25         String bban = bankCode + account; 
26         return country + checkDigits(country, bban) + bban; 
27     } 
28  
29     private static String checkDigits(String country, String bban) { 
30         StringBuilder numeric = new StringBuilder(); 
31         for (char c : (bban + country + "00").toCharArray()) { 
32             numeric.append(Character.isDigit(c) ? String.valueOf(c) : String.valueOf(c - 'A' + 10)); 
33         } 
34         int mod = new BigInteger(numeric.toString()).mod(BigInteger.valueOf(97)).intValue(); 
35         return String.format("%02d", 98 - mod); 
36     } 
37 } 

Two details matter as much as the code: 

The key is a secret. National identification numbers and customer numbers come from a small, predictable range. Without a key, anyone could hash every possible value and reverse the mapping. The key is held by the security or data protection function, never by the test team, and never stored next to the masked data. 

The same key is used across systems for one refresh, so customer and account tokens match everywhere. Changing the key for each refresh limits how far data from different refreshes can be linked. 


Approach 2: synthetic data 


Synthetic data is generated rather than copied. There are two broad ways to do it: 

Rule-based generation: a model of the bank's domain (customers, accounts, products, cards, transactions) with rules for how they relate, filled with realistic values from libraries such as Datafaker or the team's own generators. 

Model-based generation: statistical or machine learning models trained on production data that produce new records with similar patterns. 


Where synthetic data is strong 

Lowest regulatory risk. Rule-based synthetic data that isn't derived from real individuals isn't personal data at all. It can be used in developer machines, CI pipelines, vendor environments and demos without the controls that personal data needs. 

Edge cases on demand. Synthetic data can produce exactly the cases a test needs, including ones production has never seen: a transfer exactly at the daily limit, a loan maturing on a public holiday, a customer with 200 accounts, an IBAN from every SEPA country, a name in every supported character set. Each test can create its own data, which also makes tests independent and repeatable. 

Volume and shape under control. Performance tests can generate ten times today's volume, or a deliberately extreme month-end peak. 

Built for new products. A product launching next quarter has no production history. Synthetic data is the only way to test it realistically before go-live. 


Where synthetic data is weak 

Realism depends on the model. Synthetic data is only as realistic as the rules behind it. Real data is messier than anyone remembers: inconsistent legacy values, half-completed records, combinations that "can't happen" but did. Purely synthetic data tends to be cleaner than production, which means some defects only appear later. 

Referential integrity has to be designed. Every relationship must be modelled explicitly: a card belongs to an account, the account belongs to one or more customers, transactions add up to the balance, loan schedules add up to the outstanding amount, and IBANs carry valid check digits. Missing a rule produces data that passes one system's tests and fails in the next. 

Model-based generation needs its own assessment. A model trained on production data can memorise and reproduce real records, particularly rare ones. Synthetic data produced this way should be tested for privacy leakage before it is treated as non-personal. 


The BA review: where the business knowledge comes in 

Both approaches depend on knowledge that sits with business analysts as much as with testers. In our projects, the BA review covers three things: 

Field classification for masking. Every field in scope is classified: direct identifier, quasi-identifier, free text, sensitive, or non-personal. The classification decides the masking technique, and the BA is often the person who knows that a "comments" field on a loan application regularly contains medical information. 

Domain rules for synthetic data. The rules a generator must respect come from product and process knowledge: which products a customer segment can hold, how fees accrue, which statuses can follow each other. Written down once, they serve both the generator and the acceptance criteria. 

The edge-case catalogue. A shared list of the cases that must exist in test data, drawn from incidents, complaints, regulatory rules and product terms. Testers turn each entry into generated data or a check that the masked dataset contains it. 


Choosing per use case 


Neither approach wins everywhere. The right choice depends on what the data is for: 

Developer environments and CI pipelines: synthetic data only. These environments have the most people, the most copies and the weakest controls. 

Functional and regression testing: synthetic data by default, with each test creating the data it needs. Add masked data for areas where legacy data shapes behaviour. 

Performance testing: synthetic data scaled from production statistics, or masked production where realistic distribution is critical. The aggregate statistics used to shape synthetic volumes should themselves be non-identifying. 

Migration rehearsals and data-heavy reporting tests: masked production, because the goal is to prove that the real estate behaves correctly. This is also where a documented assessment, strict access control and short retention matter most. 

Reproducing a production defect: first try to recreate the case synthetically. Where that isn't possible, use the narrowest possible masked extract, or real data under the DORA derogation, approved, time-limited and reported. 


A combined approach 

The pattern that holds up best, both in testing and in regulatory reviews, combines the two: 

Synthetic first. Make rule-based synthetic data the default for all lower environments, with a generator owned like any other product, versioned and reviewed by BAs and testers. 

Masked where necessary. Use masked production data only in controlled pre-production environments, for named purposes, with a DPIA, access logging and retention limits. 

Free text removed or replaced. Treat payment references, notes and documents as the highest-risk fields in any masked dataset. 

Production only by exception. Follow DORA's derogation: specific occasion, limited time, approval and reporting. 

Feed findings back. When masked data reveals a historical edge case, add it to the edge-case catalogue so the synthetic generator covers it next time. 


Closing thought 

Realistic test data and data protection are not in conflict, but they need deliberate choices. Masking keeps the real shape and history of a bank's data but carries the regulatory weight of personal data. Synthetic data removes most of that risk but only knows what its designers put into it. Used together, with business knowledge built into both, they give testers the realism they need and give the data protection officer an approach they can defend