Test data is the data used to exercise software during development, testing, and QA, standing in for real production data so teams can build and verify features without exposing sensitive records. It generally takes four forms: raw copies of production data, masked (de-identified) production data, subsetted slices of production, and synthetic data generated to mimic production. Each form trades realism, privacy, volume, and setup effort differently.
What test data is and where it's used
Test data is any dataset used to exercise software before it meets real users — the records a feature reads, writes, and validates against while it's still being built and checked. What makes it good for the job is that it behaves like the data the system will see in production: the same shapes, the same relationships between tables, the same awkward edge cases. A test that passes against realistic data means something; one that passes against a handful of hand-typed rows often doesn't. That need for realism is what makes sourcing test data harder than it first looks.
Test data feeds nearly every environment an engineering team runs before code reaches customers:
- Local development, where an engineer needs a working dataset on their own machine to build and debug against.
- Continuous integration, where automated tests run on every commit and need fresh, predictable data to run against reliably.
- Staging, where a near-production replica validates a release end to end before it ships.
- Performance and load testing, where the dataset has to reach production scale to surface the bottlenecks that only appear under volume.
- Demos and training, where realistic-looking records make the product legible without putting anyone's real information on a screen.
The underlying tension is straightforward: teams want data that behaves exactly like production, and the most production-like data is production itself — yet copying production into these lower environments is precisely what you can't safely do. Resolving that tension is the job of test data management, and it starts with separating two questions that are easy to run together: where test data comes from, and what form it takes. Each form — raw, masked, subsetted, or synthetic — answers those questions differently, and seeing how is the foundation of what test data management is as a practice.
Production data as the starting source
The most direct source of test data is a copy of production, and it's the intuitive default because it delivers maximum realism for free: real records, real distributions, real relationships, real edge cases nobody would think to invent. If the goal is data that behaves like production, production is the highest-fidelity answer there is. This is why teams so often reach for a raw production dump first.
The problem is that a raw production copy is a liability the moment it lands in a lower environment. Development, CI, and staging are controlled far more loosely than production — more people can reach them, credentials are shared, and data lingers in places nobody is auditing. Pushing untouched production data into that setting spreads real personal and regulated information across your least-protected systems, which raises the GDPR, HIPAA, and PCI obligations in lower environments that most teams would rather keep confined to production.
The practical issues compound the compliance one:
- Sensitive-data exposure. A raw copy carries the full weight of PII and PHI into environments that were never built to safeguard it.
- Size. Production databases are often too large to stand up on a laptop or spin up per test run, so a full copy is slow and expensive to move.
- Refresh lag. Reloading a large copy takes time, so environments drift stale between refreshes and tests run against yesterday's data.
Each of these is a reason to transform the production copy rather than use it as-is — which is what the three safer forms do.
Masked (de-identified) test data
Masking transforms real production values into safe, realistic stand-ins while preserving their format and structure, so the data stays useful for testing but no longer exposes anyone. A masked email address is still a syntactically valid email; a masked date is still a plausible date; a masked account number still passes the format checks your code runs — the shape survives, only the sensitive value changes. Masking is also called de-identification, and it's the form most teams reach for when they need production's realism without production's risk.
Three properties separate masking that works from masking that quietly breaks your tests:
- Referential integrity — the relationships between tables have to survive the transformation. If a customer ID is masked one way in the orders table and another way in the customers table, the join that connected them is gone, and any test that relied on it fails for the wrong reason.
- Deterministic masking — the same input value maps to the same output value everywhere it appears. That consistency is what keeps foreign keys and joins intact across tables and across separate databases.
- Format-preserving output — masked values keep the type, length, and structure of the originals, so schema constraints and validation logic behave exactly as they do in production.
Tonic Structural is built around exactly these properties: it connects to a production database, applies data masking rules per column, and maintains referential integrity across related tables, environments, and different database types. Because Structural masks deterministically, the relationships that make data realistic hold together after transformation rather than falling apart.
The Tonic Advantage. Masking is only useful if the result still behaves like production. Structural applies masking rules column by column and keeps referential integrity intact across every related table, so the joins, foreign keys, and cross-table relationships your tests depend on survive de-identification. The output is data that's safe to move into dev, CI, and staging and still meaningful to test against — not a scrubbed dataset that breaks the moment a test touches a relationship.
Subsetted test data
Subsetting extracts a smaller, coherent slice of a larger database while keeping referential integrity intact, so a dataset a fraction of the original size still behaves like the whole. The key word is coherent: a good subset isn't a random sample of rows but a connected cut through the data, where every record you keep brings along the related records it depends on. Done right, a multi-terabyte production database becomes a few-gigabyte slice that fits on a laptop and still exercises the same code paths.
Teams subset for three practical reasons. Environments like local development or CI often can't hold a full production copy, and a subset makes them viable. Smaller datasets refresh far faster, so environments stay current instead of drifting stale. And subsetting lets you hand each developer an isolated dataset of their own, which avoids the collisions that happen when a whole team shares one environment and overwrites each other's state.
Masking and subsetting are usually combined rather than chosen between: you subset the already-masked output, so the slice you provision is both small and safe. Getting the cut right depends entirely on preserving referential integrity — a subset that drops the rows a foreign key points to is worse than no subset at all, because it fails in ways that look like application bugs. Tonic Structural includes a patented subsetter built for this: it walks the relationships in the schema to carve out a smaller database subsetting result that stays internally consistent, so the fraction-of-the-size database still holds together like the full one.
Synthetic test data
Synthetic test data is generated to mimic production's structure and statistical patterns rather than transformed from it — the records are manufactured, not derived from real ones. It's produced one of two ways: from scratch against a schema and a set of rules, or by modeling an existing dataset and generating new records that share its shape. Either way, the output carries no direct tie to a real person, because no real record was ever copied.
Synthetic data fits the cases the production-derived forms can't cover. When production is too sensitive to touch even after masking, generating fresh data sidesteps the source entirely. When a dataset is too small — a rare condition, a new customer segment — generation can produce more of the same shape. When the data doesn't exist yet, as with a greenfield feature that has no production history, synthetic data is the only option. And when you need volume and variety beyond what production holds, such as load testing at scale or exercising edge cases that occur once in a million real rows, generation gives you as much as you want.
Tonic Fabricate is a test data solution built for this generate-from-scratch approach: it produces referentially intact synthetic data from a schema you describe or from a model of an existing database, maintaining the relationships across tables that keep the data realistic. Fabricate is complementary to production-derived masking rather than a replacement for it — it answers the situations where there's no safe production data to start from. Choosing between synthetic data versus masked production data comes down to whether you have usable production data to transform, or need to manufacture data that production can't give you.
How to choose and combine the four types
The right form of test data follows from what you most need to optimize: realism, privacy, volume control, independence from production, or setup effort. Raw production maximizes realism at the cost of privacy; masking buys privacy while keeping realism; subsetting buys size and speed; synthetic generation buys independence from production and unlimited volume. Most teams don't pick one and stop — they combine them.
| Approach | Realism | Privacy | Volume control | Production dependency | Typical use |
|---|---|---|---|---|---|
| Raw production copy | Highest — it is production | None — carries all PII/PHI | None — whatever production holds | Total | Narrow; only where neither sensitivity nor scale is a concern |
| Masked production data — Tonic Structural | High — real structure and distributions, values transformed | Strong — PII/PHI replaced with safe stand-ins | Inherits production's size unless subsetted | High — derived from a production copy | Safe, production-like data for dev, CI, and staging |
| Subsetted production data — Tonic Structural | High — a coherent slice that keeps relationships | Depends — subset the masked output for safety | High — dial size down to fit the environment | High — still derived from production | Smaller, faster environments and per-developer datasets |
| Synthetic data — Tonic Fabricate | High when modeled well — patterns without copying records | Strong — no direct tie to real individuals | Full — generate as much or as little as needed | Low to none — from a schema or a model | Greenfield features, edge cases, and load and performance testing |
In practice the forms chain together. The common pipeline is to mask production, then subset the masked output, so what you provision is both safe and small — an end-to-end workflow that turns a risky production database into fast, compliant environments. Synthetic generation fills the gaps that leaves: use Tonic Structural to de-identify production, then connect Tonic Fabricate to that de-identified output to generate additional records modeled on it, scaling a dataset up for performance and load testing without reintroducing sensitive data. That pairing keeps the two products in their own lanes — Structural transforms real data, Fabricate generates new data — while letting them solve a problem neither covers alone.
Getting this right pays off directly in engineering velocity. Patterson reported a 75% reduction in test data provisioning time after automating their test data pipeline — time returned to building and debugging instead of waiting on data. For a fuller view of the categories and where each fits, the test data management tools landscape maps the options, and if you want named products weighed against one another, there are specific TDM tools compared in depth.