<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Genory Team</title>
    <description>The latest articles on DEV Community by Genory Team (@genorydev).</description>
    <link>https://dev.to/genorydev</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4163343%2F0468dc54-1016-4573-8160-49417d0b0197.png</url>
      <title>DEV Community: Genory Team</title>
      <link>https://dev.to/genorydev</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/genorydev"/>
    <language>en</language>
    <item>
      <title>Synthetic Data vs Fake Data: What's the Difference and When Should You Use Each?</title>
      <dc:creator>Genory Team</dc:creator>
      <pubDate>Sun, 18 Oct 2026 05:00:00 +0000</pubDate>
      <link>https://dev.to/genorydev/synthetic-data-vs-fake-data-whats-the-difference-and-when-should-you-use-each-4j9m</link>
      <guid>https://dev.to/genorydev/synthetic-data-vs-fake-data-whats-the-difference-and-when-should-you-use-each-4j9m</guid>
      <description>&lt;p&gt;Developers often use the terms &lt;strong&gt;fake data&lt;/strong&gt;, &lt;strong&gt;dummy data&lt;/strong&gt;, &lt;strong&gt;mock data&lt;/strong&gt;, and &lt;strong&gt;synthetic data&lt;/strong&gt; as if they all mean the same thing.&lt;/p&gt;

&lt;p&gt;Sometimes that is harmless.&lt;/p&gt;

&lt;p&gt;Sometimes it causes real confusion.&lt;/p&gt;

&lt;p&gt;Consider these two records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@test.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test City"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.schneider@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hamburg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postalCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20095"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both are not real customer records.&lt;/p&gt;

&lt;p&gt;But they serve very different purposes.&lt;/p&gt;

&lt;p&gt;The first is obviously placeholder data.&lt;/p&gt;

&lt;p&gt;The second is designed to resemble the structure and relationships found in real data.&lt;/p&gt;

&lt;p&gt;That difference becomes important when you're testing applications, APIs, imports, forms, analytics pipelines, or databases.&lt;/p&gt;

&lt;p&gt;So what exactly is synthetic data, and how is it different from ordinary fake data?&lt;/p&gt;

&lt;h2&gt;
  
  
  What is fake data?
&lt;/h2&gt;

&lt;p&gt;Fake data is any information created specifically for testing, demonstrations, development, or other non-production purposes.&lt;/p&gt;

&lt;p&gt;It can be extremely simple:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John Doe
123 Fake Street
test@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Or even:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foo
bar
123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is usually not realism.&lt;/p&gt;

&lt;p&gt;The goal is simply to have &lt;strong&gt;something&lt;/strong&gt; to put into a field.&lt;/p&gt;

&lt;p&gt;For example, if you're testing whether a form submits correctly, this might be enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"User"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@example.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Nothing about that record needs to resemble a real user.&lt;/p&gt;

&lt;p&gt;It only needs to satisfy the basic input requirements.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is synthetic data?
&lt;/h2&gt;

&lt;p&gt;Synthetic data goes a step further.&lt;/p&gt;

&lt;p&gt;It is generated data designed to imitate the &lt;strong&gt;properties, structure, distributions, or relationships&lt;/strong&gt; of real data without copying actual records.&lt;/p&gt;

&lt;p&gt;For a simple customer profile, that could mean:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.schneider@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hamburg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postalCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20095"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The person is not meant to represent a real customer.&lt;/p&gt;

&lt;p&gt;But the record is internally plausible.&lt;/p&gt;

&lt;p&gt;The fields relate to each other in a meaningful way.&lt;/p&gt;

&lt;p&gt;That makes synthetic data useful for testing systems that behave differently depending on realistic combinations of values.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fake data can be intentionally unrealistic
&lt;/h2&gt;

&lt;p&gt;Sometimes unrealistic data is exactly what you want.&lt;/p&gt;

&lt;p&gt;Suppose you're testing whether a username field accepts a value.&lt;/p&gt;

&lt;p&gt;This may be perfectly fine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You do not need a sophisticated identity generator.&lt;/p&gt;

&lt;p&gt;Likewise, if you're testing a calculator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2 + 2 = 4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;there is no benefit in generating realistic financial records.&lt;/p&gt;

&lt;p&gt;Simple fake data is often best for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unit tests&lt;/li&gt;
&lt;li&gt;simple form tests&lt;/li&gt;
&lt;li&gt;exact business rules&lt;/li&gt;
&lt;li&gt;predictable fixtures&lt;/li&gt;
&lt;li&gt;small examples&lt;/li&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The simpler the test, the simpler the data should usually be.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synthetic data is useful when relationships matter
&lt;/h2&gt;

&lt;p&gt;Now imagine a checkout system.&lt;/p&gt;

&lt;p&gt;You may need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;name
country
city
postal code
phone number
currency
tax rules
shipping options
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If every field is generated independently, you might get:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Tokyo"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postalCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SW1A 1AA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+1 212 555 0100"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every individual value looks valid.&lt;/p&gt;

&lt;p&gt;Together they make little sense.&lt;/p&gt;

&lt;p&gt;If your application uses those relationships, your tests become less useful.&lt;/p&gt;

&lt;p&gt;Synthetic data can preserve context.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hamburg"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postalCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"20095"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+49 40 12345678"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is much more useful for testing country-aware behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Dummy data is usually simpler
&lt;/h2&gt;

&lt;p&gt;The term &lt;strong&gt;dummy data&lt;/strong&gt; usually refers to placeholder information.&lt;/p&gt;

&lt;p&gt;Examples:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John Doe
Company ABC
123456
example@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It is often used for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;demos&lt;/li&gt;
&lt;li&gt;temporary UI development&lt;/li&gt;
&lt;li&gt;prototypes&lt;/li&gt;
&lt;li&gt;documentation&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Dummy data does not necessarily try to reproduce real-world distributions or relationships.&lt;/p&gt;

&lt;p&gt;It just fills space.&lt;/p&gt;

&lt;p&gt;That makes it useful.&lt;/p&gt;

&lt;p&gt;But it is not automatically realistic.&lt;/p&gt;

&lt;h2&gt;
  
  
  Mock data is slightly different
&lt;/h2&gt;

&lt;p&gt;Mock data often appears in the context of mocked systems.&lt;/p&gt;

&lt;p&gt;For example, a frontend may call an API that does not exist yet.&lt;/p&gt;

&lt;p&gt;Instead of making a real request:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;response&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;fetch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;/api/users&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the frontend might receive a mocked response:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pro"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important concept is not whether the values are realistic.&lt;/p&gt;

&lt;p&gt;The important concept is that the response &lt;strong&gt;stands in for another system&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Mocking is about replacing dependencies.&lt;/p&gt;

&lt;p&gt;Synthetic data is about generating realistic data.&lt;/p&gt;

&lt;p&gt;They can absolutely be used together.&lt;/p&gt;

&lt;p&gt;A mocked API can return synthetic data.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test fixtures are about repeatability
&lt;/h2&gt;

&lt;p&gt;A fixture is data prepared for a test.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;user&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;id&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;user-42&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;plan&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pro&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;balance&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;100&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fixtures are often deliberately static.&lt;/p&gt;

&lt;p&gt;That is useful because the expected state is obvious.&lt;/p&gt;

&lt;p&gt;If a test fails, you know exactly what the input was.&lt;/p&gt;

&lt;p&gt;Synthetic data can also be used as a fixture, especially when it is seeded.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = checkout-user-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generator can recreate the same synthetic customer every time.&lt;/p&gt;

&lt;p&gt;That combines realism with reproducibility.&lt;/p&gt;

&lt;h2&gt;
  
  
  Realism should match the test
&lt;/h2&gt;

&lt;p&gt;One mistake developers make is assuming that more realistic data is always better.&lt;/p&gt;

&lt;p&gt;It isn't.&lt;/p&gt;

&lt;p&gt;Suppose you're testing this function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;addTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;price&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nx"&gt;price&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;rate&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably want a test like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;addTax&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;0.19&lt;/span&gt;&lt;span class="p"&gt;)).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;119&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generating a realistic customer, address, order, product catalog, and payment method adds nothing.&lt;/p&gt;

&lt;p&gt;But if you're testing a full checkout flow, realistic synthetic data becomes much more useful.&lt;/p&gt;

&lt;p&gt;A simple rule:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Use the least complicated data that still tests the behavior you care about.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Production data is not test data
&lt;/h2&gt;

&lt;p&gt;There is another category developers sometimes use:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;copied production data&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export 1,000 customers
import into staging
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This may create realistic test conditions.&lt;/p&gt;

&lt;p&gt;It also creates privacy and security risks.&lt;/p&gt;

&lt;p&gt;Production data can contain:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;names&lt;/li&gt;
&lt;li&gt;emails&lt;/li&gt;
&lt;li&gt;addresses&lt;/li&gt;
&lt;li&gt;phone numbers&lt;/li&gt;
&lt;li&gt;account identifiers&lt;/li&gt;
&lt;li&gt;transaction histories&lt;/li&gt;
&lt;li&gt;internal notes&lt;/li&gt;
&lt;li&gt;sensitive metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Once copied into development, that information may appear in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local databases&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;test exports&lt;/li&gt;
&lt;li&gt;bug reports&lt;/li&gt;
&lt;li&gt;backups&lt;/li&gt;
&lt;li&gt;developer laptops&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Synthetic data avoids this problem by generating new records rather than copying actual customers.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synthetic does not automatically mean anonymous
&lt;/h2&gt;

&lt;p&gt;This distinction is important.&lt;/p&gt;

&lt;p&gt;If you take real customer data and simply replace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;John Smith
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;User 123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;the dataset is not necessarily synthetic.&lt;/p&gt;

&lt;p&gt;Other attributes may still allow the person to be identified.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;location
age
transaction history
rare job title
specific timestamp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can potentially reveal identity when combined.&lt;/p&gt;

&lt;p&gt;Truly synthetic data should be generated rather than merely renaming real individuals.&lt;/p&gt;

&lt;h2&gt;
  
  
  Format-valid data is another category
&lt;/h2&gt;

&lt;p&gt;Sometimes realism means following a technical format.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UUID
IBAN
MAC address
IMEI
IP address
phone number
email
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A useful test value may need to satisfy structural rules.&lt;/p&gt;

&lt;p&gt;For example, this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is not very useful for testing a real IBAN validator.&lt;/p&gt;

&lt;p&gt;You may instead need an identifier that follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;country length
BBAN structure
checksum rules
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That makes the test data technically realistic.&lt;/p&gt;

&lt;p&gt;But an important distinction remains:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Format-valid does not mean real-world verified.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A generated IBAN can satisfy structural checks without representing an existing bank account.&lt;/p&gt;

&lt;p&gt;A generated device identifier can match the expected format without representing an actual device.&lt;/p&gt;

&lt;h2&gt;
  
  
  Synthetic data can preserve distributions
&lt;/h2&gt;

&lt;p&gt;For some applications, individual realistic records are not enough.&lt;/p&gt;

&lt;p&gt;Imagine testing analytics.&lt;/p&gt;

&lt;p&gt;Production data might contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;70% free users
20% standard users
10% premium users
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A naive generator could produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;33% free
33% standard
33% premium
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may create misleading results.&lt;/p&gt;

&lt;p&gt;A more advanced synthetic dataset could preserve the intended distribution:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;free: 70%
standard: 20%
premium: 10%
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Likewise, synthetic datasets can model relationships such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;country → currency
country → phone format
product → price range
subscription → feature usage
age group → behavior
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This becomes useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;analytics&lt;/li&gt;
&lt;li&gt;machine learning testing&lt;/li&gt;
&lt;li&gt;load testing&lt;/li&gt;
&lt;li&gt;dashboards&lt;/li&gt;
&lt;li&gt;data pipelines&lt;/li&gt;
&lt;li&gt;BI systems&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Synthetic data can still contain edge cases
&lt;/h2&gt;

&lt;p&gt;Realistic does not mean normal.&lt;/p&gt;

&lt;p&gt;Good test datasets should include unusual scenarios.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;very long names
empty optional values
Unicode characters
leap-day dates
zero-value orders
duplicate records
minimum values
maximum values
unusual postal formats
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;These cases often expose more bugs than ordinary records.&lt;/p&gt;

&lt;p&gt;A good synthetic-data system should allow realism and deliberate edge cases to coexist.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: signup testing
&lt;/h2&gt;

&lt;p&gt;For a simple unit test, this may be enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@example.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For integration testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.schneider@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For edge-case testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"A"&lt;/span&gt;&lt;span class="err"&gt;.repeat(&lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="err"&gt;)&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna+very-long-alias@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Different tests deserve different data strategies.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: API testing
&lt;/h2&gt;

&lt;p&gt;Imagine this endpoint:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST /customers
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The API expects:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"string"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A basic fixture could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"123"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may be enough to test JSON parsing.&lt;/p&gt;

&lt;p&gt;But it is not very useful for testing phone validation.&lt;/p&gt;

&lt;p&gt;A realistic synthetic fixture could be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.schneider@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+49 40 12345678"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the same payload exercises more realistic application behavior.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example: database testing
&lt;/h2&gt;

&lt;p&gt;Suppose you need 100,000 customer rows.&lt;/p&gt;

&lt;p&gt;Writing static fixtures is obviously impractical.&lt;/p&gt;

&lt;p&gt;A synthetic generator can create:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;100,000 records
multiple countries
different subscription plans
varied signup dates
different order histories
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;query testing&lt;/li&gt;
&lt;li&gt;pagination&lt;/li&gt;
&lt;li&gt;indexing&lt;/li&gt;
&lt;li&gt;search&lt;/li&gt;
&lt;li&gt;analytics&lt;/li&gt;
&lt;li&gt;performance testing&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For this kind of workload, synthetic data becomes much more valuable than simple dummy records.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeds make synthetic data reproducible
&lt;/h2&gt;

&lt;p&gt;Pure generation introduces a problem:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;run 1 → dataset A
run 2 → dataset B
run 3 → dataset C
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If dataset A exposes a bug, you may want it again.&lt;/p&gt;

&lt;p&gt;That is where seeds help.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = regression-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can produce the same synthetic dataset repeatedly.&lt;/p&gt;

&lt;p&gt;Then a CI failure can report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generator: customer
Seed: regression-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer can recreate the exact input locally.&lt;/p&gt;

&lt;p&gt;This makes synthetic data much more practical for automated testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't use synthetic data everywhere
&lt;/h2&gt;

&lt;p&gt;Synthetic data is not the answer to every problem.&lt;/p&gt;

&lt;p&gt;Use static fixtures when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;exact values matter&lt;/li&gt;
&lt;li&gt;the test is small&lt;/li&gt;
&lt;li&gt;readability is important&lt;/li&gt;
&lt;li&gt;business rules are simple&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use synthetic data when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;realistic variation matters&lt;/li&gt;
&lt;li&gt;you need many records&lt;/li&gt;
&lt;li&gt;relationships between fields matter&lt;/li&gt;
&lt;li&gt;you want multiple locales&lt;/li&gt;
&lt;li&gt;you need performance datasets&lt;/li&gt;
&lt;li&gt;production data should not be copied&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use deliberately invalid data when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;testing validators&lt;/li&gt;
&lt;li&gt;testing error messages&lt;/li&gt;
&lt;li&gt;testing edge cases&lt;/li&gt;
&lt;li&gt;testing defensive code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The best test suite usually combines all three.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical hierarchy
&lt;/h2&gt;

&lt;p&gt;I like to think about test data in layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 1: Placeholder data
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;foo
bar
123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for very simple tests.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 2: Static fixtures
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"test@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"plan"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"pro"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for predictable business logic.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 3: Synthetic records
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.schneider@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hamburg"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for realistic application testing.&lt;/p&gt;

&lt;h3&gt;
  
  
  Level 4: Synthetic datasets
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10,000 related records
multiple countries
weighted distributions
edge cases
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Useful for analytics, system testing, and performance testing.&lt;/p&gt;

&lt;p&gt;The higher the level, the more complexity you introduce.&lt;/p&gt;

&lt;p&gt;Only move up when the test actually benefits from it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where tools like Genory fit
&lt;/h2&gt;

&lt;p&gt;Developer tools such as &lt;a href="https://genory.dev/tools" rel="noopener noreferrer"&gt;Genory&lt;/a&gt; focus on generating synthetic test data and structured developer fixtures without requiring real customer records.&lt;/p&gt;

&lt;p&gt;For example, you can work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;synthetic profiles&lt;/li&gt;
&lt;li&gt;custom datasets&lt;/li&gt;
&lt;li&gt;addresses&lt;/li&gt;
&lt;li&gt;UUIDs&lt;/li&gt;
&lt;li&gt;format-based test identifiers&lt;/li&gt;
&lt;li&gt;validators&lt;/li&gt;
&lt;li&gt;developer utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For more complex fixture generation, you can start with the &lt;a href="https://genory.dev/tools/test-data" rel="noopener noreferrer"&gt;Genory test-data tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For programmatic workflows, the current API documentation is available at &lt;a href="https://genory.dev/docs" rel="noopener noreferrer"&gt;genory.dev/docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;The goal is not to replace explicit test fixtures.&lt;/p&gt;

&lt;p&gt;The goal is to make realistic test data easier to create when realism actually helps.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple rule
&lt;/h2&gt;

&lt;p&gt;When choosing test data, ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does this test care about the exact value?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If yes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use an explicit fixture.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no, ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does realism matter?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If no:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use simple fake data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If yes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use synthetic data.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And if the test must be reproducible:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use a seed.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Fake data and synthetic data are not enemies.&lt;/p&gt;

&lt;p&gt;They solve different problems.&lt;/p&gt;

&lt;p&gt;Fake data is often simple, obvious, and predictable.&lt;/p&gt;

&lt;p&gt;Synthetic data is useful when your tests benefit from realistic structure, relationships, variation, or scale.&lt;/p&gt;

&lt;p&gt;The mistake is not choosing one over the other.&lt;/p&gt;

&lt;p&gt;The mistake is using complicated data where simple fixtures would work — or using meaningless placeholders when your application depends on realistic relationships.&lt;/p&gt;

&lt;p&gt;Choose the data based on the behavior you're trying to test.&lt;/p&gt;

&lt;p&gt;Not based on which generator looks more impressive.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>programming</category>
      <category>webdev</category>
      <category>privacy</category>
    </item>
    <item>
      <title>10 Small Developer Tools That Save Time During Testing</title>
      <dc:creator>Genory Team</dc:creator>
      <pubDate>Thu, 15 Oct 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/genorydev/10-small-developer-tools-that-save-time-during-testing-4n9a</link>
      <guid>https://dev.to/genorydev/10-small-developer-tools-that-save-time-during-testing-4n9a</guid>
      <description>&lt;p&gt;Testing usually isn't slowed down by one huge problem.&lt;/p&gt;

&lt;p&gt;It is slowed down by dozens of tiny interruptions.&lt;/p&gt;

&lt;p&gt;You need a UUID.&lt;/p&gt;

&lt;p&gt;Then a realistic test profile.&lt;/p&gt;

&lt;p&gt;Then a valid-looking IBAN for a form test.&lt;/p&gt;

&lt;p&gt;Then a random MAC address.&lt;/p&gt;

&lt;p&gt;Then you need to compare two values, generate another dataset, or check whether an identifier has the right structure.&lt;/p&gt;

&lt;p&gt;None of these tasks is difficult.&lt;/p&gt;

&lt;p&gt;But every context switch costs time.&lt;/p&gt;

&lt;p&gt;Here are 10 small developer tools and workflows that can make everyday testing faster.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. UUID Generator
&lt;/h2&gt;

&lt;p&gt;UUIDs are one of the most common identifiers used in modern applications.&lt;/p&gt;

&lt;p&gt;You may need them for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;database records&lt;/li&gt;
&lt;li&gt;API resources&lt;/li&gt;
&lt;li&gt;test fixtures&lt;/li&gt;
&lt;li&gt;message IDs&lt;/li&gt;
&lt;li&gt;temporary objects&lt;/li&gt;
&lt;li&gt;distributed systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Instead of manually inventing IDs like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;test-user-123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can generate proper UUIDs.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;550e8400-e29b-41d4-a716-446655440000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For many projects, UUID v4 is still the simplest choice.&lt;/p&gt;

&lt;p&gt;For newer systems where time grouping is useful, UUID v7 can also be interesting.&lt;/p&gt;

&lt;p&gt;A good UUID tool should make it easy to generate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;UUID v4
UUID v7
multiple UUIDs at once
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without opening a terminal or writing a helper script.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Synthetic Profile Generator
&lt;/h2&gt;

&lt;p&gt;Sometimes you need more than a single random value.&lt;/p&gt;

&lt;p&gt;You need a complete test profile:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"firstName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lastName"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"anna.schneider@example.com"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Hamburg"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;signup flows&lt;/li&gt;
&lt;li&gt;CRM testing&lt;/li&gt;
&lt;li&gt;account creation&lt;/li&gt;
&lt;li&gt;admin dashboards&lt;/li&gt;
&lt;li&gt;imports&lt;/li&gt;
&lt;li&gt;UI screenshots&lt;/li&gt;
&lt;li&gt;API payloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The important part is that the data is synthetic.&lt;/p&gt;

&lt;p&gt;You should not have to copy real customer records into development just to make a form look realistic.&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Custom Test Data Generator
&lt;/h2&gt;

&lt;p&gt;Predefined profiles are convenient, but sometimes you need your own schema.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;customer_name
email
order_total
status
created_at
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A custom generator lets you define fields instead of accepting a huge generic profile.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"customer_name"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fullName"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"order_total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"decimal"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"choice"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That gives you exactly the dataset your test needs.&lt;/p&gt;

&lt;p&gt;Not 30 unrelated fields.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Address Generator
&lt;/h2&gt;

&lt;p&gt;Address forms are surprisingly annoying to test.&lt;/p&gt;

&lt;p&gt;A typical address includes several related values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;street
house number
city
postal code
region
country
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Randomly generating each field independently can create unrealistic combinations.&lt;/p&gt;

&lt;p&gt;For UI and validation testing, it is often more useful to generate addresses that at least resemble the expected structure for a country.&lt;/p&gt;

&lt;p&gt;This helps when testing:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;checkout forms&lt;/li&gt;
&lt;li&gt;delivery forms&lt;/li&gt;
&lt;li&gt;CRM systems&lt;/li&gt;
&lt;li&gt;location fields&lt;/li&gt;
&lt;li&gt;imports&lt;/li&gt;
&lt;li&gt;validation rules&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The goal is not to generate a real resident.&lt;/p&gt;

&lt;p&gt;The goal is to produce realistic-looking test input.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. IBAN Validator
&lt;/h2&gt;

&lt;p&gt;Banking forms are another place where random strings are not very useful.&lt;/p&gt;

&lt;p&gt;An IBAN validator can check things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;country format
length
BBAN structure
MOD-97 checksum
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That makes it easy to build targeted test cases.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;valid structure
wrong checksum
wrong length
unsupported country
illegal character
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One important distinction:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A format-valid IBAN is not proof that a real bank account exists.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That matters both in your code and in the wording of your UI.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Password Generator
&lt;/h2&gt;

&lt;p&gt;Developers often need passwords for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;test accounts&lt;/li&gt;
&lt;li&gt;local environments&lt;/li&gt;
&lt;li&gt;demos&lt;/li&gt;
&lt;li&gt;seeded users&lt;/li&gt;
&lt;li&gt;staging systems&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;password123
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into every test account is convenient but unrealistic.&lt;/p&gt;

&lt;p&gt;A password generator lets you test things like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;minimum length
uppercase requirements
special characters
numbers
very long passwords
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For actual secrets, use a proper cryptographically secure generator.&lt;/p&gt;

&lt;p&gt;For UI testing, generated passwords are also useful for checking how forms behave with different lengths and character sets.&lt;/p&gt;

&lt;h2&gt;
  
  
  7. MAC Address Generator
&lt;/h2&gt;

&lt;p&gt;If you work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;networking tools&lt;/li&gt;
&lt;li&gt;device management&lt;/li&gt;
&lt;li&gt;inventory systems&lt;/li&gt;
&lt;li&gt;IoT software&lt;/li&gt;
&lt;li&gt;hardware dashboards&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;you may need MAC-address fixtures.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;00:1A:2B:3C:4D:5E
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A dedicated generator is faster than manually editing old values.&lt;/p&gt;

&lt;p&gt;It also helps avoid accidentally reusing production device identifiers in demos or screenshots.&lt;/p&gt;

&lt;h2&gt;
  
  
  8. IMEI Test Data
&lt;/h2&gt;

&lt;p&gt;Mobile-device systems sometimes require IMEI-shaped values.&lt;/p&gt;

&lt;p&gt;That can happen in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;device registration&lt;/li&gt;
&lt;li&gt;telecom dashboards&lt;/li&gt;
&lt;li&gt;inventory systems&lt;/li&gt;
&lt;li&gt;mobile-device management&lt;/li&gt;
&lt;li&gt;validation forms&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, the useful distinction is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;format-valid test data
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;versus:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;verified real-world device
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are not the same thing.&lt;/p&gt;

&lt;p&gt;A generator can help you test formatting and validation logic without using real device identifiers.&lt;/p&gt;

&lt;h2&gt;
  
  
  9. Reproducible Seeded Data
&lt;/h2&gt;

&lt;p&gt;Random data is great until a test fails.&lt;/p&gt;

&lt;p&gt;Suppose your CI pipeline generates a customer profile and triggers a bug.&lt;/p&gt;

&lt;p&gt;You run the test again.&lt;/p&gt;

&lt;p&gt;Different data.&lt;/p&gt;

&lt;p&gt;The bug disappears.&lt;/p&gt;

&lt;p&gt;This is why seeded generation is useful.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;random data every time
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = checkout-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the generator is deterministic, the same seed produces the same fixture.&lt;/p&gt;

&lt;p&gt;That makes bug reports much more useful:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test failed
Generator: customer-profile
Seed: checkout-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now another developer can reproduce the exact same dataset.&lt;/p&gt;

&lt;h2&gt;
  
  
  10. API-Based Generation
&lt;/h2&gt;

&lt;p&gt;Manual tools are perfect when you're exploring.&lt;/p&gt;

&lt;p&gt;Automation becomes useful when you repeat the same workflow.&lt;/p&gt;

&lt;p&gt;Instead of opening a browser every time, your test setup can request synthetic data programmatically.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s2"&gt;"https://genory.dev/api/profile"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$GENORY_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "country": "DE",
    "amount": 1,
    "fields": ["firstName", "lastName", "email"]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the fixture can be created from:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;test scripts&lt;/li&gt;
&lt;li&gt;CI pipelines&lt;/li&gt;
&lt;li&gt;local development tools&lt;/li&gt;
&lt;li&gt;seed scripts&lt;/li&gt;
&lt;li&gt;API tests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That removes repetitive manual work.&lt;/p&gt;

&lt;h2&gt;
  
  
  The real value is reducing context switching
&lt;/h2&gt;

&lt;p&gt;None of these tools is revolutionary by itself.&lt;/p&gt;

&lt;p&gt;That is exactly the point.&lt;/p&gt;

&lt;p&gt;Developer productivity is often improved by removing small interruptions.&lt;/p&gt;

&lt;p&gt;Consider this workflow:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Need UUID
↓
Search for generator
↓
Need address
↓
Search again
↓
Need IBAN validation
↓
Open another site
↓
Need synthetic profile
↓
Write temporary script
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every step is small.&lt;/p&gt;

&lt;p&gt;Together they create friction.&lt;/p&gt;

&lt;p&gt;A single toolbox can reduce that to:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;open tools
↓
generate
↓
copy
↓
continue working
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is where small utilities become valuable.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep test data separate from production data
&lt;/h2&gt;

&lt;p&gt;There is also a security and privacy benefit.&lt;/p&gt;

&lt;p&gt;Development environments often have weaker controls than production.&lt;/p&gt;

&lt;p&gt;Test data can end up in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;li&gt;local databases&lt;/li&gt;
&lt;li&gt;bug reports&lt;/li&gt;
&lt;li&gt;developer laptops&lt;/li&gt;
&lt;li&gt;staging environments&lt;/li&gt;
&lt;li&gt;temporary exports&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Synthetic data reduces the temptation to copy real customer information into those places.&lt;/p&gt;

&lt;p&gt;It does not solve every security problem.&lt;/p&gt;

&lt;p&gt;But it removes one unnecessary source of risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use the right tool for the job
&lt;/h2&gt;

&lt;p&gt;A useful rule is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Need exact business-rule test?
→ Write an explicit fixture.

Need realistic variation?
→ Use synthetic data.

Need reproducibility?
→ Add a seed.

Need automation?
→ Use an API.

Need production verification?
→ Use the appropriate real verification service.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No generator should replace actual business validation when real-world verification is required.&lt;/p&gt;

&lt;h2&gt;
  
  
  One toolbox instead of ten tabs
&lt;/h2&gt;

&lt;p&gt;This is also the idea behind &lt;a href="https://genory.dev/tools" rel="noopener noreferrer"&gt;Genory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It combines developer utilities, synthetic test-data generators and validators in one place.&lt;/p&gt;

&lt;p&gt;For example, you can work with:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;synthetic profiles&lt;/li&gt;
&lt;li&gt;custom datasets&lt;/li&gt;
&lt;li&gt;UUIDs&lt;/li&gt;
&lt;li&gt;addresses&lt;/li&gt;
&lt;li&gt;IBAN validation&lt;/li&gt;
&lt;li&gt;device-format test data&lt;/li&gt;
&lt;li&gt;other development utilities&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For UUID testing specifically, there is a dedicated &lt;a href="https://genory.dev/tools/uuid-generator" rel="noopener noreferrer"&gt;UUID Generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For banking-format tests, you can use the &lt;a href="https://genory.dev/tools/iban-validator" rel="noopener noreferrer"&gt;IBAN Validator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And for programmatic workflows, the current API documentation is available at &lt;a href="https://genory.dev/docs" rel="noopener noreferrer"&gt;genory.dev/docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;The best developer tools are not always the biggest ones.&lt;/p&gt;

&lt;p&gt;Sometimes the most useful tool is the one that saves you 30 seconds.&lt;/p&gt;

&lt;p&gt;Because saving 30 seconds once is irrelevant.&lt;/p&gt;

&lt;p&gt;Saving 30 seconds fifty times a week is a workflow improvement.&lt;/p&gt;

&lt;p&gt;Remove the tiny interruptions.&lt;/p&gt;

&lt;p&gt;Keep your test data synthetic.&lt;/p&gt;

&lt;p&gt;Automate what becomes repetitive.&lt;/p&gt;

&lt;p&gt;And spend more time testing your application than preparing data for the test.&lt;/p&gt;

</description>
      <category>productivity</category>
      <category>softwaredevelopment</category>
      <category>testing</category>
      <category>tools</category>
    </item>
    <item>
      <title>How to Build Reproducible Test Fixtures with Seeded Synthetic Data</title>
      <dc:creator>Genory Team</dc:creator>
      <pubDate>Tue, 13 Oct 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/genorydev/how-to-build-reproducible-test-fixtures-with-seeded-synthetic-data-30m9</link>
      <guid>https://dev.to/genorydev/how-to-build-reproducible-test-fixtures-with-seeded-synthetic-data-30m9</guid>
      <description>&lt;p&gt;Random test data is useful.&lt;/p&gt;

&lt;p&gt;Until a test fails.&lt;/p&gt;

&lt;p&gt;Then randomness can become your enemy.&lt;/p&gt;

&lt;p&gt;Imagine a CI job fails with a generated dataset containing a specific combination of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;name&lt;/li&gt;
&lt;li&gt;country&lt;/li&gt;
&lt;li&gt;date&lt;/li&gt;
&lt;li&gt;order value&lt;/li&gt;
&lt;li&gt;status&lt;/li&gt;
&lt;li&gt;identifier&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You run the test again.&lt;/p&gt;

&lt;p&gt;It passes.&lt;/p&gt;

&lt;p&gt;Run it a third time.&lt;/p&gt;

&lt;p&gt;It passes again.&lt;/p&gt;

&lt;p&gt;The failure is gone because the generator created different data.&lt;/p&gt;

&lt;p&gt;This is exactly where seeded synthetic data becomes useful.&lt;/p&gt;

&lt;p&gt;A seed lets you keep the benefits of generated test data while making the output reproducible.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a seed actually do?
&lt;/h2&gt;

&lt;p&gt;A deterministic generator starts with an initial value:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = 42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The generator uses that value as the starting state for producing pseudo-random values.&lt;/p&gt;

&lt;p&gt;If the algorithm and configuration remain the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = 42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should produce the same sequence again.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed 42
  ↓
Anna
Hamburg
20095
€184.22
active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it again with the same seed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed 42
  ↓
Anna
Hamburg
20095
€184.22
active
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Change the seed:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed 43
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and you get a different dataset.&lt;/p&gt;

&lt;p&gt;That makes the seed a compact way to describe an entire generated fixture.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why this matters in CI
&lt;/h2&gt;

&lt;p&gt;Consider a test like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;test&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkout accepts generated customer data&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;async &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateCustomer&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;checkout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;customer&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="nf"&gt;expect&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;result&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;success&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nf"&gt;toBe&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If &lt;code&gt;generateCustomer()&lt;/code&gt; returns different values every time, a failure can be difficult to reproduce.&lt;/p&gt;

&lt;p&gt;Instead, imagine:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;customer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateCustomer&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;checkout-1842&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now your CI output can report:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Test failed.
Seed: checkout-1842
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A developer can run the test locally using exactly the same seed.&lt;/p&gt;

&lt;p&gt;That turns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"It failed once in CI."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;into:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;"Run this exact dataset."
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a huge debugging improvement.&lt;/p&gt;

&lt;h2&gt;
  
  
  Randomness is not the same as unpredictability
&lt;/h2&gt;

&lt;p&gt;Developers sometimes assume that test data should always be completely unpredictable.&lt;/p&gt;

&lt;p&gt;Usually it should not.&lt;/p&gt;

&lt;p&gt;Production systems may need cryptographically secure randomness.&lt;/p&gt;

&lt;p&gt;Test fixtures usually need something else:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;controlled variation&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You want datasets that differ enough to expose assumptions while still being reproducible when something breaks.&lt;/p&gt;

&lt;p&gt;For testing, deterministic pseudo-randomness is often more useful than true randomness.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple seeded generator
&lt;/h2&gt;

&lt;p&gt;Here is a deliberately small example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;createRng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;function &lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1664525&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1013904223&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;state&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;4294967296&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Calling the same function again with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;createRng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;12345&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;produces the same sequence.&lt;/p&gt;

&lt;p&gt;For real applications, you would normally use a mature deterministic PRNG library rather than inventing one.&lt;/p&gt;

&lt;p&gt;The important idea is the deterministic relationship:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;same seed + same algorithm = same sequence
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Build fixtures from the seeded source
&lt;/h2&gt;

&lt;p&gt;Once you have a seeded random source, other values should derive from it.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;index&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;index&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;createRng&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;DE&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;FR&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;NL&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;pick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;active&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;pending&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;blocked&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you recreate the generator with seed &lt;code&gt;42&lt;/code&gt;, you should receive the same choices.&lt;/p&gt;

&lt;p&gt;That is the foundation of reproducible synthetic data.&lt;/p&gt;

&lt;h2&gt;
  
  
  The whole pipeline must be deterministic
&lt;/h2&gt;

&lt;p&gt;A common mistake is seeding only one part of the generator.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;seededRandom&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generatedFromSeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;email&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generatedFromSeed&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;createdAt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nc"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The name and email are reproducible.&lt;/p&gt;

&lt;p&gt;The timestamp is not.&lt;/p&gt;

&lt;p&gt;If reproducibility matters, avoid hidden dynamic inputs such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;current time
machine hostname
process ID
random UUID
timezone
environment-specific ordering
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Instead, make them explicit inputs.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;generateFixture&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="na"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="na"&gt;now&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;2026-10-05T12:00:00Z&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now both randomness and time are controlled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Version your fixture generators
&lt;/h2&gt;

&lt;p&gt;There is another subtle problem.&lt;/p&gt;

&lt;p&gt;Imagine this configuration:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = 42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;generates:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Anna Schneider"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then six months later you improve your generator.&lt;/p&gt;

&lt;p&gt;You add more names and change the country selection algorithm.&lt;/p&gt;

&lt;p&gt;Now seed &lt;code&gt;42&lt;/code&gt; might produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Jonas Weber"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NL"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Technically, the seed stayed the same.&lt;/p&gt;

&lt;p&gt;But the generator changed.&lt;/p&gt;

&lt;p&gt;If you rely heavily on reproducibility, save the generator version too:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;generatorVersion = 3
seed = 42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A failure report can then contain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Fixture generator: v3
Seed: 42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is much more reliable than storing only the seed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeds should describe scenarios
&lt;/h2&gt;

&lt;p&gt;You do not have to use numbers.&lt;/p&gt;

&lt;p&gt;Readable seeds can make test output easier to understand.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checkout-basic
checkout-eu-user
checkout-large-order
import-invalid-address
profile-long-name
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Internally, the string can be hashed into a numeric seed.&lt;/p&gt;

&lt;p&gt;This gives your tests meaningful names while preserving deterministic generation.&lt;/p&gt;

&lt;p&gt;Instead of:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;generateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;91281&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can write:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;generateUser&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;signup-german-user&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The second version communicates intent.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't make every test depend on huge generated profiles
&lt;/h2&gt;

&lt;p&gt;Synthetic-data systems can generate enormous records.&lt;/p&gt;

&lt;p&gt;That does not mean every test should use them.&lt;/p&gt;

&lt;p&gt;Suppose you are testing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;email normalization
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Test.User@Example.com"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You probably do not need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"address"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"company"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"job"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"iban"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"device"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"orderHistory"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Large fixtures increase cognitive load.&lt;/p&gt;

&lt;p&gt;Generate only what the test actually needs.&lt;/p&gt;

&lt;p&gt;A useful principle is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Small deterministic fixtures for unit tests, richer synthetic datasets for integration and system tests.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Separate normal fixtures from edge cases
&lt;/h2&gt;

&lt;p&gt;Pure randomness is surprisingly bad at finding many important bugs.&lt;/p&gt;

&lt;p&gt;A generator may happily produce normal data thousands of times without ever creating:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;an empty string
a 255-character name
February 29
a negative value
a duplicate identifier
a zero-value order
a Unicode-heavy address
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So combine generated fixtures with deliberate edge cases.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;cases&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;
  &lt;span class="nf"&gt;generateCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;normal-customer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="nf"&gt;generateCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;another-customer&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
  &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="p"&gt;...&lt;/span&gt;&lt;span class="nf"&gt;generateCustomer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;long-name&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;A&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;repeat&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;];&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Randomness should complement scenario design, not replace it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep relationships between fields deterministic
&lt;/h2&gt;

&lt;p&gt;Realistic fixtures often contain dependent fields.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;country = DE
city = Hamburg
postalCode = 20095
phonePrefix = +49
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A poor generator might independently produce:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;country = DE
city = Toronto
postalCode = SW1A 1AA
phonePrefix = +81
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That may be useful for some validation tests.&lt;/p&gt;

&lt;p&gt;But it is not a realistic German profile.&lt;/p&gt;

&lt;p&gt;If your application depends on relationships between fields, derive those values from the same deterministic context.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;country&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateCountry&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;address&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generateAddress&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;country&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;

&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;phone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;generatePhone&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
  &lt;span class="nx"&gt;random&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="nx"&gt;country&lt;/span&gt;
&lt;span class="p"&gt;});&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the fixture stays coherent while remaining reproducible.&lt;/p&gt;

&lt;h2&gt;
  
  
  Save the seed when reporting errors
&lt;/h2&gt;

&lt;p&gt;If generated data is used in automated tests, always include the seed in failure output.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;try&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;runCheckoutTest&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fixture&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;catch &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`Fixture seed: &lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;throw&lt;/span&gt; &lt;span class="nx"&gt;error&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your CI logs might then show:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FAIL checkout.integration.test.js

Expected: 200
Received: 500

Fixture seed: checkout-regression-9381
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That one line may save an hour of debugging.&lt;/p&gt;

&lt;h2&gt;
  
  
  Seeds are also useful outside automated tests
&lt;/h2&gt;

&lt;p&gt;Reproducible datasets help with more than CI.&lt;/p&gt;

&lt;h3&gt;
  
  
  Bug reports
&lt;/h3&gt;

&lt;p&gt;Instead of attaching a huge JSON file:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Use seed: bug-2841
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  UI development
&lt;/h3&gt;

&lt;p&gt;Designers and frontend developers can repeatedly work with the same profile dataset.&lt;/p&gt;

&lt;h3&gt;
  
  
  Database demos
&lt;/h3&gt;

&lt;p&gt;Seeded data keeps screenshots and demonstrations consistent.&lt;/p&gt;

&lt;h3&gt;
  
  
  Performance testing
&lt;/h3&gt;

&lt;p&gt;Specific seeds can represent different dataset shapes.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;small-shop
enterprise-customer
high-order-volume
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  QA
&lt;/h3&gt;

&lt;p&gt;A tester can send a developer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generator: profile
Seed: qa-login-114
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Both sides can reproduce the same data.&lt;/p&gt;

&lt;h2&gt;
  
  
  But don't mistake seeds for security
&lt;/h2&gt;

&lt;p&gt;A deterministic seed is not a secret.&lt;/p&gt;

&lt;p&gt;If someone knows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = customer-demo
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and knows the generator algorithm, they may be able to reproduce the same data.&lt;/p&gt;

&lt;p&gt;That is completely fine for synthetic test fixtures.&lt;/p&gt;

&lt;p&gt;It is not fine for generating:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;passwords&lt;/li&gt;
&lt;li&gt;encryption keys&lt;/li&gt;
&lt;li&gt;API tokens&lt;/li&gt;
&lt;li&gt;password-reset tokens&lt;/li&gt;
&lt;li&gt;session secrets&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Security-sensitive values require cryptographically secure generation.&lt;/p&gt;

&lt;p&gt;Seeded fixture generation and secure random generation solve different problems.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical test-data strategy
&lt;/h2&gt;

&lt;p&gt;A good setup might contain three layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: Explicit fixtures
&lt;/h3&gt;

&lt;p&gt;For exact business rules:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"price"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;100&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"discount"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 2: Seeded synthetic fixtures
&lt;/h3&gt;

&lt;p&gt;For realistic variation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = checkout-customer-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 3: Randomized exploratory tests
&lt;/h3&gt;

&lt;p&gt;For discovering unexpected combinations:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;random seed generated per run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The trick is to log the random seed.&lt;/p&gt;

&lt;p&gt;If an exploratory run fails:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Random seed: 9182811
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you can convert an unpredictable failure into a reproducible one.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate random seeds — but record them
&lt;/h2&gt;

&lt;p&gt;This gives you a useful hybrid approach.&lt;/p&gt;

&lt;p&gt;At test startup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;seed&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt;
  &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TEST_SEED&lt;/span&gt; &lt;span class="o"&gt;??&lt;/span&gt;
  &lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;floor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;random&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="nx"&gt;_000_000&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then print it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;`TEST_SEED=&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;seed&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Your CI run might use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TEST_SEED=718421
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If the test fails, reproduce it locally:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;TEST_SEED&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;718421 npm &lt;span class="nb"&gt;test&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now each CI execution explores new data while every failure remains reproducible.&lt;/p&gt;

&lt;p&gt;That is often the best of both worlds.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using Genory for reproducible datasets
&lt;/h2&gt;

&lt;p&gt;You can experiment with synthetic test data using the &lt;a href="https://genory.dev/tools/test-data" rel="noopener noreferrer"&gt;Genory Test Data tools&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For dataset-style workflows, Genory can help generate structured test records while keeping development data separate from real customer information.&lt;/p&gt;

&lt;p&gt;For programmatic workflows and supported endpoints, the current API documentation is available at:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://genory.dev/docs" rel="noopener noreferrer"&gt;genory.dev/docs&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Whether you use Genory, a local fixture library, or your own generator, the underlying principle remains the same:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;configuration
+
seed
+
generator version
=
reproducible fixture
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  A useful failure report
&lt;/h2&gt;

&lt;p&gt;Instead of logging an entire fixture, you may be able to log:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Generator: customer-profile
Version: 3
Seed: checkout-regression-9381
Locale: de-DE
Now: 2026-10-05T12:00:00Z
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is enough information to reconstruct the dataset.&lt;/p&gt;

&lt;p&gt;It is compact, searchable and easy to paste into a bug report.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Generated test data should not make bugs harder to reproduce.&lt;/p&gt;

&lt;p&gt;It should make bugs easier to discover.&lt;/p&gt;

&lt;p&gt;The key is controlling randomness instead of eliminating it.&lt;/p&gt;

&lt;p&gt;Use synthetic data to introduce variation.&lt;/p&gt;

&lt;p&gt;Use seeds to make that variation repeatable.&lt;/p&gt;

&lt;p&gt;And whenever a randomized test fails, save the seed.&lt;/p&gt;

&lt;p&gt;Because:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A random failure you cannot reproduce is frustrating.&lt;/p&gt;

&lt;p&gt;A random failure with a seed is a test case.&lt;/p&gt;
&lt;/blockquote&gt;

</description>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
      <category>testing</category>
    </item>
    <item>
      <title>How IBAN Validation Actually Works (and What It Does Not Prove)</title>
      <dc:creator>Genory Team</dc:creator>
      <pubDate>Sat, 10 Oct 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/genorydev/how-iban-validation-actually-works-and-what-it-does-not-prove-3h1m</link>
      <guid>https://dev.to/genorydev/how-iban-validation-actually-works-and-what-it-does-not-prove-3h1m</guid>
      <description>&lt;p&gt;An IBAN validator often looks deceptively simple.&lt;/p&gt;

&lt;p&gt;A user enters something like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The application shows a green checkmark.&lt;/p&gt;

&lt;p&gt;Done, right?&lt;/p&gt;

&lt;p&gt;Not quite.&lt;/p&gt;

&lt;p&gt;A valid-looking IBAN can pass several mathematical and structural checks without proving that the bank account actually exists, belongs to a particular person, or can receive a payment.&lt;/p&gt;

&lt;p&gt;For developers, that distinction matters.&lt;/p&gt;

&lt;p&gt;Let's look at what IBAN validation really does.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is inside an IBAN?
&lt;/h2&gt;

&lt;p&gt;An IBAN — International Bank Account Number — is a structured identifier.&lt;/p&gt;

&lt;p&gt;At a high level, it contains:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;COUNTRY + CHECK DIGITS + BBAN
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;can be viewed conceptually as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE | 89 | 370400440532013000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The first two characters are the country code.&lt;/p&gt;

&lt;p&gt;The next two digits are check digits.&lt;/p&gt;

&lt;p&gt;The remaining part is the BBAN — the country-specific Basic Bank Account Number.&lt;/p&gt;

&lt;p&gt;The important detail is that the BBAN structure differs by country.&lt;/p&gt;

&lt;p&gt;Germany does not use the same internal structure as the Netherlands or the United Kingdom.&lt;/p&gt;

&lt;p&gt;So an IBAN validator should do more than simply check:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;starts with two letters
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Step 1: Normalize the input
&lt;/h2&gt;

&lt;p&gt;Users rarely type an IBAN in exactly one format.&lt;/p&gt;

&lt;p&gt;You may receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;de89370400440532013000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89370400440532013000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A validator usually starts by normalizing the value.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;normalized&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;iban&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;replace&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sr"&gt;/&lt;/span&gt;&lt;span class="se"&gt;\s&lt;/span&gt;&lt;span class="sr"&gt;+/g&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="dl"&gt;""&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;toUpperCase&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After normalization:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89370400440532013000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This normalized value is much easier to validate and store consistently.&lt;/p&gt;

&lt;p&gt;A useful rule is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Store the normalized identifier and add spaces only for display.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Also remember that an IBAN is text.&lt;/p&gt;

&lt;p&gt;Do not treat it as a number.&lt;/p&gt;

&lt;p&gt;Leading zeros may be meaningful.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Check the country code
&lt;/h2&gt;

&lt;p&gt;The first two characters identify the IBAN country or territory format.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE → Germany
NL → Netherlands
GB → United Kingdom
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A validator should confirm that the prefix represents a supported IBAN format.&lt;/p&gt;

&lt;p&gt;If you receive:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZZ123456789
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;and &lt;code&gt;ZZ&lt;/code&gt; is not part of your supported format table, you should reject it before doing deeper checks.&lt;/p&gt;

&lt;p&gt;This also determines which country-specific length and BBAN rules should be applied.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Check the expected length
&lt;/h2&gt;

&lt;p&gt;IBANs do not all have the same length.&lt;/p&gt;

&lt;p&gt;The required length depends on the country.&lt;/p&gt;

&lt;p&gt;That means this is not enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;iban&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;15&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;iban&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;length&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;=&lt;/span&gt; &lt;span class="mi"&gt;34&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// valid?&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A proper validator should ask:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;What is the expected length for this country?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then compare the normalized input against that exact value.&lt;/p&gt;

&lt;p&gt;For example, if a specific country's IBAN format requires 22 characters, then:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;21 characters → invalid
22 characters → continue validation
23 characters → invalid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Length validation catches many common input errors immediately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;missing characters&lt;/li&gt;
&lt;li&gt;accidental extra digits&lt;/li&gt;
&lt;li&gt;truncated copy/paste&lt;/li&gt;
&lt;li&gt;wrong country format&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But length alone obviously does not prove that the IBAN is correct.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: Validate the BBAN structure
&lt;/h2&gt;

&lt;p&gt;The part after the first four characters is the country-specific BBAN.&lt;/p&gt;

&lt;p&gt;This is where country formats become more interesting.&lt;/p&gt;

&lt;p&gt;One country may expect:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bank code + account number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Another might include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;bank code + branch code + account number
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Some formats contain only digits.&lt;/p&gt;

&lt;p&gt;Others allow letters.&lt;/p&gt;

&lt;p&gt;For developers, this means a validator may need country-specific patterns.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;rules&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="na"&gt;DE&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;22&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;bbanPattern&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="sr"&gt;/^&lt;/span&gt;&lt;span class="se"&gt;[&lt;/span&gt;&lt;span class="sr"&gt;0-9&lt;/span&gt;&lt;span class="se"&gt;]{18}&lt;/span&gt;&lt;span class="sr"&gt;$/&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="c1"&gt;// additional country definitions...&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Real implementations need a complete and maintained rule source rather than a tiny hardcoded example like this.&lt;/p&gt;

&lt;p&gt;The important principle is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Validate according to the selected country's structure, not one universal regular expression.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Step 5: The MOD-97 checksum
&lt;/h2&gt;

&lt;p&gt;This is the part most people associate with IBAN validation.&lt;/p&gt;

&lt;p&gt;IBANs use a checksum based on modulo 97.&lt;/p&gt;

&lt;p&gt;The algorithm is elegant.&lt;/p&gt;

&lt;p&gt;Start with a normalized IBAN:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89370400440532013000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Move the first four characters to the end:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;370400440532013000DE89
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then convert letters to numbers.&lt;/p&gt;

&lt;p&gt;The mapping is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;A = 10
B = 11
C = 12
...
Z = 35
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;D = 13
E = 14
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The rearranged value becomes a very large numeric string.&lt;/p&gt;

&lt;p&gt;Then calculate:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;number mod 97
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A valid IBAN produces:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;remainder = 1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;mod97&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;convertedValue&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;===&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// checksum passes&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Don't parse the entire value as one JavaScript number
&lt;/h2&gt;

&lt;p&gt;This is an important implementation detail.&lt;/p&gt;

&lt;p&gt;The converted numeric string can be much larger than JavaScript's safe integer range.&lt;/p&gt;

&lt;p&gt;So this is a bad idea:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;hugeIbanNumber&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can lose precision.&lt;/p&gt;

&lt;p&gt;Instead, calculate the modulo incrementally.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;mod97&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;numberString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;let&lt;/span&gt; &lt;span class="nx"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;for &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;digit&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="nx"&gt;numberString&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;remainder&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="nc"&gt;Number&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;digit&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="mi"&gt;97&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;remainder&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This never requires representing the entire giant number at once.&lt;/p&gt;

&lt;p&gt;The same concept works in almost any programming language.&lt;/p&gt;

&lt;h2&gt;
  
  
  What does a passing checksum actually prove?
&lt;/h2&gt;

&lt;p&gt;This is the most important part of the article.&lt;/p&gt;

&lt;p&gt;A passing MOD-97 check proves something very specific:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;The characters are mathematically consistent with the IBAN checksum.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That is useful.&lt;/p&gt;

&lt;p&gt;It can detect many:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;mistyped digits&lt;/li&gt;
&lt;li&gt;transcription errors&lt;/li&gt;
&lt;li&gt;malformed values&lt;/li&gt;
&lt;li&gt;accidental character changes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it does &lt;strong&gt;not&lt;/strong&gt; prove that:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;the account exists&lt;/li&gt;
&lt;li&gt;the account is open&lt;/li&gt;
&lt;li&gt;the account belongs to the person entering it&lt;/li&gt;
&lt;li&gt;the bank details are currently active&lt;/li&gt;
&lt;li&gt;the account can receive a particular payment&lt;/li&gt;
&lt;li&gt;the account has a balance&lt;/li&gt;
&lt;li&gt;the payment will succeed&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That difference should also appear in your user interface.&lt;/p&gt;

&lt;p&gt;Instead of displaying:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Bank account verified ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;a format validator should say something more precise:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IBAN format and checksum valid ✓
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Those are very different claims.&lt;/p&gt;

&lt;h2&gt;
  
  
  Format validation vs account verification
&lt;/h2&gt;

&lt;p&gt;A good mental model is to separate validation into layers.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 1: Syntax
&lt;/h3&gt;

&lt;p&gt;Questions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does it contain allowed characters?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 2: Country and length
&lt;/h3&gt;

&lt;p&gt;Questions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does the country exist in the supported IBAN format list?
Does this value have the expected number of characters?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 3: BBAN structure
&lt;/h3&gt;

&lt;p&gt;Questions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does the country-specific bank/account portion match the expected shape?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 4: International checksum
&lt;/h3&gt;

&lt;p&gt;Questions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does MOD-97 return 1?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Layer 5: National rules
&lt;/h3&gt;

&lt;p&gt;Some countries have additional bank-code or account-number checks.&lt;/p&gt;

&lt;p&gt;These rules are not identical across all IBAN countries.&lt;/p&gt;

&lt;h3&gt;
  
  
  Layer 6: Real-world verification
&lt;/h3&gt;

&lt;p&gt;This is outside normal offline IBAN validation.&lt;/p&gt;

&lt;p&gt;Questions such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Does this bank account exist?
Who owns it?
Can it receive this payment?
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;usually require a bank, payment provider, directory or verification service.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why your API should expose validation details
&lt;/h2&gt;

&lt;p&gt;Returning only this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;is often not enough.&lt;/p&gt;

&lt;p&gt;A more useful response might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"valid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"lengthValid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"structureValid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"checksumValid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nationalCheckPerformed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now the calling application understands what was actually checked.&lt;/p&gt;

&lt;p&gt;That distinction is especially useful when validation coverage differs between countries.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"checksumValid"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"nationalCheckPerformed"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;should not automatically be interpreted as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;everything about this bank account has been verified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It simply means that one additional validation layer was not performed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Build useful negative test cases
&lt;/h2&gt;

&lt;p&gt;When testing an IBAN validator, don't just use:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;asdf
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;as your invalid example.&lt;/p&gt;

&lt;p&gt;Create targeted failure cases.&lt;/p&gt;

&lt;p&gt;Start with a known fixture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then modify one property at a time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Wrong checksum
&lt;/h3&gt;

&lt;p&gt;Change one check digit:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE88 3704 0044 0532 0130 00
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;checksum failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Wrong length
&lt;/h3&gt;

&lt;p&gt;Remove one character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;length failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Invalid characters
&lt;/h3&gt;

&lt;p&gt;Insert an illegal character:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;DE89 3704 0044 0532 0130 @0
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;character or structure failure
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Unsupported country
&lt;/h3&gt;

&lt;p&gt;Use an unsupported prefix:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ZZ89...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Expected result:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;unsupported country
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Testing one failure at a time makes debugging much easier.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't confuse a BIC with IBAN validation
&lt;/h2&gt;

&lt;p&gt;Another common misconception is that a BIC automatically verifies an IBAN.&lt;/p&gt;

&lt;p&gt;A BIC identifies a financial institution or branch format.&lt;/p&gt;

&lt;p&gt;An IBAN identifies an account-format structure.&lt;/p&gt;

&lt;p&gt;Even if both strings look syntactically valid, that does not automatically prove that:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;this IBAN belongs to this BIC
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That relationship requires additional reference data or provider-level verification.&lt;/p&gt;

&lt;p&gt;So treat them as separate validation problems unless you explicitly have data linking them.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don't use random strings as payment test data
&lt;/h2&gt;

&lt;p&gt;If you are building a real payment integration, you normally should not invent arbitrary bank details and attempt to process them.&lt;/p&gt;

&lt;p&gt;Use the sandbox or test credentials supplied by your payment provider.&lt;/p&gt;

&lt;p&gt;Synthetic IBANs are useful for things like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;form validation&lt;/li&gt;
&lt;li&gt;formatting&lt;/li&gt;
&lt;li&gt;imports&lt;/li&gt;
&lt;li&gt;exports&lt;/li&gt;
&lt;li&gt;database fields&lt;/li&gt;
&lt;li&gt;UI tests&lt;/li&gt;
&lt;li&gt;checksum handling&lt;/li&gt;
&lt;li&gt;API schemas&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But provider-issued sandbox data should be used for actual payment-flow testing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A simple IBAN validation pipeline
&lt;/h2&gt;

&lt;p&gt;A practical validation pipeline might look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;INPUT
  ↓
Normalize spaces and case
  ↓
Check allowed characters
  ↓
Read country code
  ↓
Check country-specific length
  ↓
Check BBAN structure
  ↓
Run MOD-97
  ↓
Run available national checks
  ↓
Return detailed result
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice what is not in that pipeline:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Ask bank whether account exists
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is a completely different operation.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try validation yourself
&lt;/h2&gt;

&lt;p&gt;You can inspect these layers with the &lt;a href="https://genory.dev/tools/iban-validator" rel="noopener noreferrer"&gt;Genory IBAN Validator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;It reports country format, length, BBAN structure and MOD-97 results separately rather than treating every successful check as proof of an existing account.&lt;/p&gt;

&lt;p&gt;For broader validation tools, Genory also has a dedicated &lt;a href="https://genory.dev/tools/validators" rel="noopener noreferrer"&gt;validator collection&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And if you're creating repeatable test cases programmatically, the current developer documentation is available at &lt;a href="https://genory.dev/docs" rel="noopener noreferrer"&gt;genory.dev/docs&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  A useful rule for your UI
&lt;/h2&gt;

&lt;p&gt;If your software performs offline IBAN validation, avoid messages like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Account verified
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Prefer language such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;IBAN format is valid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Format and checksum passed
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That is more accurate for both developers and users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;IBAN validation is a great example of why the word &lt;strong&gt;valid&lt;/strong&gt; can be dangerous in software.&lt;/p&gt;

&lt;p&gt;A value can be:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;syntactically valid
structurally valid
checksum valid
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;without being:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a verified real-world bank account
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Good validation code does more than return true or false.&lt;/p&gt;

&lt;p&gt;It makes clear &lt;strong&gt;which claim was actually proven&lt;/strong&gt;.&lt;/p&gt;

</description>
      <category>fintech</category>
      <category>softwaredevelopment</category>
      <category>softwareengineering</category>
    </item>
    <item>
      <title>UUID v4 vs UUID v7: Which One Should Developers Use in 2026?</title>
      <dc:creator>Genory Team</dc:creator>
      <pubDate>Wed, 07 Oct 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/genorydev/uuid-v4-vs-uuid-v7-which-one-should-developers-use-in-2026-ona</link>
      <guid>https://dev.to/genorydev/uuid-v4-vs-uuid-v7-which-one-should-developers-use-in-2026-ona</guid>
      <description>&lt;p&gt;UUIDs are everywhere.&lt;/p&gt;

&lt;p&gt;They identify users, orders, API resources, database rows, events, uploads and almost anything else that needs a unique ID without relying on a central counter.&lt;/p&gt;

&lt;p&gt;For years, UUID v4 has been the obvious default.&lt;/p&gt;

&lt;p&gt;Then UUID v7 arrived.&lt;/p&gt;

&lt;p&gt;Both produce 128-bit identifiers. Both can work well in distributed systems. But they solve the problem differently — and that difference can matter once your application starts storing millions of records.&lt;/p&gt;

&lt;p&gt;So when should you use UUID v4, and when does UUID v7 make more sense?&lt;/p&gt;

&lt;p&gt;Let's compare them.&lt;/p&gt;

&lt;h2&gt;
  
  
  UUID v4 in one sentence
&lt;/h2&gt;

&lt;p&gt;UUID v4 is essentially a randomly generated identifier.&lt;/p&gt;

&lt;p&gt;A typical UUID v4 looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;550e8400-e29b-41d4-a716-446655440000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The important property is that independently generated UUIDs have an extremely low probability of colliding.&lt;/p&gt;

&lt;p&gt;That makes v4 convenient for distributed systems because multiple services can generate IDs without coordinating with one another.&lt;/p&gt;

&lt;p&gt;You don't need:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a central sequence&lt;/li&gt;
&lt;li&gt;a database round trip&lt;/li&gt;
&lt;li&gt;a shared counter&lt;/li&gt;
&lt;li&gt;knowledge of previously generated IDs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Generate one and move on.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why UUID v4 became so popular
&lt;/h2&gt;

&lt;p&gt;UUID v4 has several attractive properties.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. It is simple
&lt;/h3&gt;

&lt;p&gt;Most languages and platforms already have mature support for UUID v4.&lt;/p&gt;

&lt;p&gt;For example, modern JavaScript can generate one with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;crypto&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;randomUUID&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

&lt;span class="nx"&gt;console&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;id&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is very little to configure.&lt;/p&gt;

&lt;h3&gt;
  
  
  2. Generation is decentralized
&lt;/h3&gt;

&lt;p&gt;Imagine several application servers creating new records at the same time.&lt;/p&gt;

&lt;p&gt;With an auto-incrementing integer, the database usually becomes responsible for assigning the next value.&lt;/p&gt;

&lt;p&gt;With UUIDs, each server can generate its own identifier before the record even reaches the database.&lt;/p&gt;

&lt;p&gt;That is useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;distributed systems&lt;/li&gt;
&lt;li&gt;offline workflows&lt;/li&gt;
&lt;li&gt;event generation&lt;/li&gt;
&lt;li&gt;message queues&lt;/li&gt;
&lt;li&gt;client-side object creation&lt;/li&gt;
&lt;li&gt;microservices&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  3. IDs do not reveal obvious sequence counts
&lt;/h3&gt;

&lt;p&gt;Consider URLs such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/orders/18421
/orders/18422
/orders/18423
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Someone can immediately see that the values are sequential.&lt;/p&gt;

&lt;p&gt;A UUID looks more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;/orders/550e8400-e29b-41d4-a716-446655440000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This makes the identifier less predictable.&lt;/p&gt;

&lt;p&gt;But an important warning:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An unpredictable identifier is not an authorization mechanism.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Your application must still check whether the current user is allowed to access that resource.&lt;/p&gt;

&lt;p&gt;UUIDs are identifiers, not passwords.&lt;/p&gt;

&lt;h2&gt;
  
  
  The downside of randomness
&lt;/h2&gt;

&lt;p&gt;Randomness is also where UUID v4 can become less attractive for some databases.&lt;/p&gt;

&lt;p&gt;Imagine a database index containing identifiers in sorted order.&lt;/p&gt;

&lt;p&gt;Now insert these random values:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;a82f...
14c9...
f931...
72ab...
09e1...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;New records may belong in completely different areas of the index.&lt;/p&gt;

&lt;p&gt;Depending on your database, storage engine, index structure and workload, highly random inserts can create more scattered writes than mostly increasing values.&lt;/p&gt;

&lt;p&gt;This does &lt;strong&gt;not&lt;/strong&gt; mean:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;UUID v4 is always slow.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That would be an oversimplification.&lt;/p&gt;

&lt;p&gt;Database behavior depends on many factors:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;database engine&lt;/li&gt;
&lt;li&gt;UUID storage type&lt;/li&gt;
&lt;li&gt;index implementation&lt;/li&gt;
&lt;li&gt;page size&lt;/li&gt;
&lt;li&gt;write volume&lt;/li&gt;
&lt;li&gt;caching&lt;/li&gt;
&lt;li&gt;hardware&lt;/li&gt;
&lt;li&gt;query patterns&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For many applications, UUID v4 performs perfectly well.&lt;/p&gt;

&lt;p&gt;But the desire for UUID-style decentralized identifiers that also have useful time ordering is one reason UUID v7 is interesting.&lt;/p&gt;

&lt;h2&gt;
  
  
  What UUID v7 changes
&lt;/h2&gt;

&lt;p&gt;UUID v7 still gives you a 128-bit UUID, but part of the value represents a Unix timestamp with millisecond precision.&lt;/p&gt;

&lt;p&gt;The remaining portion provides randomness.&lt;/p&gt;

&lt;p&gt;Conceptually, think of it like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;TIME + RANDOMNESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;rather than:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;RANDOMNESS
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This gives UUID v7 an important property:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UUIDs generated at different times naturally group by generation time.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A UUID v7 might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0199a4c2-96f8-7b32-a847-84e7f61a66d9
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It still looks and behaves like a UUID.&lt;/p&gt;

&lt;p&gt;But unlike v4, it contains temporal information.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why time ordering can be useful
&lt;/h2&gt;

&lt;p&gt;Suppose your application creates these records:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;10:00 → record A
10:01 → record B
10:02 → record C
10:03 → record D
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;UUID v4 values might sort like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;d82...
19a...
f71...
52c...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;There is no relationship between lexical order and creation time.&lt;/p&gt;

&lt;p&gt;UUID v7 values generated across different milliseconds naturally group more like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0199a...
0199b...
0199c...
0199d...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This can be useful for systems that create large numbers of records.&lt;/p&gt;

&lt;p&gt;Potential use cases include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;event tables&lt;/li&gt;
&lt;li&gt;logs&lt;/li&gt;
&lt;li&gt;transactions&lt;/li&gt;
&lt;li&gt;orders&lt;/li&gt;
&lt;li&gt;messages&lt;/li&gt;
&lt;li&gt;activity feeds&lt;/li&gt;
&lt;li&gt;distributed writes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Time-grouped identifiers can also behave more naturally in some indexed storage workloads.&lt;/p&gt;

&lt;p&gt;Again, that does not guarantee that changing from v4 to v7 will magically make your database faster.&lt;/p&gt;

&lt;p&gt;Benchmark your actual workload.&lt;/p&gt;

&lt;h2&gt;
  
  
  UUID v4 vs UUID v7
&lt;/h2&gt;

&lt;p&gt;Here is the practical comparison.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;UUID v4&lt;/th&gt;
&lt;th&gt;UUID v7&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Main input&lt;/td&gt;
&lt;td&gt;Randomness&lt;/td&gt;
&lt;td&gt;Timestamp + randomness&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Decentralized generation&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Natural time grouping&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Creation time embedded&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Approximate time&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Easy library support&lt;/td&gt;
&lt;td&gt;Excellent&lt;/td&gt;
&lt;td&gt;Increasing rapidly&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Good for generic IDs&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;td&gt;Yes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Useful for time-heavy workloads&lt;/td&gt;
&lt;td&gt;Possible&lt;/td&gt;
&lt;td&gt;Often attractive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Predictable sequence&lt;/td&gt;
&lt;td&gt;No&lt;/td&gt;
&lt;td&gt;Time component is observable&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Neither is universally better.&lt;/p&gt;

&lt;p&gt;They optimize for slightly different priorities.&lt;/p&gt;

&lt;h2&gt;
  
  
  One subtle limitation: the same millisecond
&lt;/h2&gt;

&lt;p&gt;It is tempting to describe UUID v7 as:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;perfectly ordered by creation time&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That is not quite correct.&lt;/p&gt;

&lt;p&gt;UUID v7 includes a millisecond timestamp.&lt;/p&gt;

&lt;p&gt;If several UUIDs are generated during the &lt;strong&gt;same millisecond&lt;/strong&gt;, the timestamp portion can be identical.&lt;/p&gt;

&lt;p&gt;Unless the implementation adds a monotonic strategy, their relative ordering inside that millisecond is not guaranteed to represent exact creation order.&lt;/p&gt;

&lt;p&gt;So a safer description is:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UUID v7 provides time grouping across milliseconds.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If strict ordering matters, use an explicit timestamp or sequence designed for that requirement.&lt;/p&gt;

&lt;h2&gt;
  
  
  UUID v7 exposes time information
&lt;/h2&gt;

&lt;p&gt;There is another tradeoff.&lt;/p&gt;

&lt;p&gt;UUID v4 does not encode its creation timestamp.&lt;/p&gt;

&lt;p&gt;UUID v7 does.&lt;/p&gt;

&lt;p&gt;That means someone inspecting a UUID v7 can derive an approximate generation time from it.&lt;/p&gt;

&lt;p&gt;For most application IDs, that may be completely acceptable.&lt;/p&gt;

&lt;p&gt;But it matters if hiding creation time is part of your threat model.&lt;/p&gt;

&lt;p&gt;For example, you may not want publicly exposed identifiers to reveal when a sensitive resource was created.&lt;/p&gt;

&lt;p&gt;Again:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Choose an identifier based on your requirements, not because one version is newer.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  What about database primary keys?
&lt;/h2&gt;

&lt;p&gt;This is where the debate becomes interesting.&lt;/p&gt;

&lt;p&gt;For a new application, you might be choosing between:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;BIGINT auto increment
UUID v4
UUID v7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Each has advantages.&lt;/p&gt;

&lt;h3&gt;
  
  
  Auto-incrementing integers
&lt;/h3&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;compact&lt;/li&gt;
&lt;li&gt;naturally ordered&lt;/li&gt;
&lt;li&gt;excellent database support&lt;/li&gt;
&lt;li&gt;easy to debug&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;usually database-generated&lt;/li&gt;
&lt;li&gt;require coordination&lt;/li&gt;
&lt;li&gt;expose simple sequence information when public&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UUID v4
&lt;/h3&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;decentralized&lt;/li&gt;
&lt;li&gt;mature&lt;/li&gt;
&lt;li&gt;unpredictable&lt;/li&gt;
&lt;li&gt;easy to generate almost anywhere&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;random index distribution&lt;/li&gt;
&lt;li&gt;no time information&lt;/li&gt;
&lt;li&gt;larger than common integer IDs&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  UUID v7
&lt;/h3&gt;

&lt;p&gt;Advantages:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;decentralized&lt;/li&gt;
&lt;li&gt;time-grouped&lt;/li&gt;
&lt;li&gt;UUID-compatible&lt;/li&gt;
&lt;li&gt;often friendlier to ordered workloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Tradeoffs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;exposes approximate creation time&lt;/li&gt;
&lt;li&gt;newer ecosystem support&lt;/li&gt;
&lt;li&gt;not strictly ordered within every millisecond&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is no universal winner.&lt;/p&gt;

&lt;h2&gt;
  
  
  Store UUIDs properly
&lt;/h2&gt;

&lt;p&gt;Another performance mistake has nothing to do with the UUID version.&lt;/p&gt;

&lt;p&gt;It is how the UUID is stored.&lt;/p&gt;

&lt;p&gt;A UUID is 128 bits.&lt;/p&gt;

&lt;p&gt;Its human-readable representation contains 36 characters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;550e8400-e29b-41d4-a716-446655440000
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But storing every UUID as a generic text field is not always necessary.&lt;/p&gt;

&lt;p&gt;Many databases provide dedicated UUID types.&lt;/p&gt;

&lt;p&gt;For example, PostgreSQL supports:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight sql"&gt;&lt;code&gt;&lt;span class="k"&gt;CREATE&lt;/span&gt; &lt;span class="k"&gt;TABLE&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;UUID&lt;/span&gt; &lt;span class="k"&gt;PRIMARY&lt;/span&gt; &lt;span class="k"&gt;KEY&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the database's native UUID type can provide clearer semantics and more efficient storage than treating identifiers as arbitrary strings.&lt;/p&gt;

&lt;p&gt;Always check what your database supports.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I would choose UUID v4
&lt;/h2&gt;

&lt;p&gt;UUID v4 remains a good choice when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;you want maximum ecosystem compatibility&lt;/li&gt;
&lt;li&gt;random identifiers are desirable&lt;/li&gt;
&lt;li&gt;your current system already uses v4&lt;/li&gt;
&lt;li&gt;write ordering is not a concern&lt;/li&gt;
&lt;li&gt;you do not want the ID to encode creation time&lt;/li&gt;
&lt;li&gt;your database workload already performs well&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There is little reason to migrate a working application from v4 solely because v7 exists.&lt;/p&gt;

&lt;h2&gt;
  
  
  When I would choose UUID v7
&lt;/h2&gt;

&lt;p&gt;For a new application, I would seriously consider UUID v7 when:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;records are frequently inserted&lt;/li&gt;
&lt;li&gt;time grouping is useful&lt;/li&gt;
&lt;li&gt;IDs are stored in indexed database columns&lt;/li&gt;
&lt;li&gt;multiple services generate identifiers&lt;/li&gt;
&lt;li&gt;you want sortable UUID-style identifiers&lt;/li&gt;
&lt;li&gt;exposing approximate creation time is acceptable&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is particularly interesting for systems dealing with large chronological datasets.&lt;/p&gt;

&lt;p&gt;Think:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;events
messages
orders
logs
audit records
transactions
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Don't use UUIDs as secrets
&lt;/h2&gt;

&lt;p&gt;This deserves repeating.&lt;/p&gt;

&lt;p&gt;Neither UUID v4 nor UUID v7 should replace proper secrets.&lt;/p&gt;

&lt;p&gt;Do not treat a UUID as equivalent to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;an API key&lt;/li&gt;
&lt;li&gt;session token&lt;/li&gt;
&lt;li&gt;password-reset token&lt;/li&gt;
&lt;li&gt;authentication token&lt;/li&gt;
&lt;li&gt;authorization rule&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Even when an identifier is difficult to guess, your application should still enforce access control.&lt;/p&gt;

&lt;p&gt;Use cryptographically appropriate tokens for security-sensitive purposes.&lt;/p&gt;

&lt;h2&gt;
  
  
  Try both versions
&lt;/h2&gt;

&lt;p&gt;Sometimes the easiest way to understand the difference is simply to generate both.&lt;/p&gt;

&lt;p&gt;You can compare UUID v4 and v7 using the &lt;a href="https://genory.dev/tools/uuid-generator" rel="noopener noreferrer"&gt;Genory UUID Generator&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Generate several v4 values and notice how unrelated they appear.&lt;/p&gt;

&lt;p&gt;Then generate several v7 values and compare identifiers created at different times.&lt;/p&gt;

&lt;p&gt;Genory also exposes UUID generation through its developer API. For supported API access, the current documentation is available at &lt;a href="https://genory.dev/docs" rel="noopener noreferrer"&gt;genory.dev/docs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Conceptually, the API supports choosing the UUID version:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version = v4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;or:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;version = v7
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That makes it easy to test how both identifier strategies behave in your own fixtures before making an architectural decision.&lt;/p&gt;

&lt;h2&gt;
  
  
  So which one should you use in 2026?
&lt;/h2&gt;

&lt;p&gt;For an existing system successfully using UUID v4:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Keep using v4 unless you have a concrete reason to change.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For a new application where UUIDs will become heavily indexed database keys:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UUID v7 deserves serious consideration.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For identifiers where you do not want to reveal approximate creation time:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UUID v4 may be preferable.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;For systems where chronological grouping is useful:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;UUID v7 is often the more interesting choice.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The most important rule is not:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Always use the newest UUID version.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;It is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Understand what information your identifier contains and how your storage system will use it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;UUID v4 solved an important distributed-systems problem extremely well.&lt;/p&gt;

&lt;p&gt;UUID v7 does not replace it.&lt;/p&gt;

&lt;p&gt;Instead, v7 adds something many modern applications can benefit from: &lt;strong&gt;time-aware ordering without giving up decentralized UUID generation.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;That makes the decision surprisingly simple:&lt;/p&gt;

&lt;p&gt;Use v4 when randomness is exactly what you need.&lt;/p&gt;

&lt;p&gt;Use v7 when time grouping gives your system an advantage.&lt;/p&gt;

&lt;p&gt;And if performance is the reason you're choosing between them, benchmark your own database instead of trusting a rule of thumb.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>webdev</category>
      <category>database</category>
      <category>api</category>
    </item>
    <item>
      <title>How to Generate Realistic Test Data Without Using Real Customer Data</title>
      <dc:creator>Genory Team</dc:creator>
      <pubDate>Mon, 05 Oct 2026 09:00:27 +0000</pubDate>
      <link>https://dev.to/genory/how-to-generate-realistic-test-data-without-using-real-customer-data-11l5</link>
      <guid>https://dev.to/genory/how-to-generate-realistic-test-data-without-using-real-customer-data-11l5</guid>
      <description>&lt;p&gt;Realistic test data is one of those things that seems simple until you actually need it.&lt;/p&gt;

&lt;p&gt;A signup form might only require a name and an email address. But a real application often needs much more:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;names&lt;/li&gt;
&lt;li&gt;addresses&lt;/li&gt;
&lt;li&gt;phone numbers&lt;/li&gt;
&lt;li&gt;dates&lt;/li&gt;
&lt;li&gt;UUIDs&lt;/li&gt;
&lt;li&gt;company information&lt;/li&gt;
&lt;li&gt;account-format data&lt;/li&gt;
&lt;li&gt;custom fields&lt;/li&gt;
&lt;li&gt;relationships between fields&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The obvious shortcut is to copy a few rows from production.&lt;/p&gt;

&lt;p&gt;That is also one of the worst habits a development team can build.&lt;/p&gt;

&lt;p&gt;In this article, we'll look at a safer and more useful approach: generating synthetic test data designed specifically for development and QA.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why production data should stay out of your test environment
&lt;/h2&gt;

&lt;p&gt;Using real customer information may make test data look realistic, but it introduces unnecessary risk.&lt;/p&gt;

&lt;p&gt;Development, staging and demo environments often have different security controls than production. Data may end up in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;local databases&lt;/li&gt;
&lt;li&gt;screenshots&lt;/li&gt;
&lt;li&gt;bug reports&lt;/li&gt;
&lt;li&gt;log files&lt;/li&gt;
&lt;li&gt;test exports&lt;/li&gt;
&lt;li&gt;developer laptops&lt;/li&gt;
&lt;li&gt;temporary environments&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A much better principle is:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Test the structure and behavior of your application without copying the people behind the data.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Synthetic test data gives you values that resemble the data your application expects while remaining independent from actual customer records.&lt;/p&gt;

&lt;h2&gt;
  
  
  Random data is not always good test data
&lt;/h2&gt;

&lt;p&gt;Generating random strings is easy.&lt;/p&gt;

&lt;p&gt;Generating useful test data is harder.&lt;/p&gt;

&lt;p&gt;Consider an address form.&lt;/p&gt;

&lt;p&gt;This is technically random:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: Xkqpd Azzw
City: 48291
Phone: foo-bar
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it doesn't help much when testing a real user interface.&lt;/p&gt;

&lt;p&gt;A more useful fixture might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Name: Anna Schneider
Email: anna.schneider@example.com
Country: DE
City: Hamburg
Postal code: 20095
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The goal is not to create a real person.&lt;/p&gt;

&lt;p&gt;The goal is to produce data that behaves like the type of input your application is designed to process.&lt;/p&gt;

&lt;h2&gt;
  
  
  Keep related fields related
&lt;/h2&gt;

&lt;p&gt;One common mistake is generating every column independently.&lt;/p&gt;

&lt;p&gt;Imagine this row:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"country"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"DE"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"postalCode"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SW1A 1AA"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"phone"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"+81..."&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"city"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Toronto"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Every individual value may look plausible, but the record as a whole is useless for many tests.&lt;/p&gt;

&lt;p&gt;For profile-style fixtures, related fields should share context.&lt;/p&gt;

&lt;p&gt;Names, addresses, phone formats and country settings should make sense together whenever your test actually depends on that relationship.&lt;/p&gt;

&lt;p&gt;For tests where relationships don't matter, you can deliberately generate fields independently.&lt;/p&gt;

&lt;p&gt;The important part is making that choice intentionally.&lt;/p&gt;

&lt;h2&gt;
  
  
  Use reserved domains for test email addresses
&lt;/h2&gt;

&lt;p&gt;Email addresses are another surprisingly easy source of trouble.&lt;/p&gt;

&lt;p&gt;Avoid generating random addresses on real domains such as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;randomperson@gmail.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You don't know whether that address actually belongs to someone.&lt;/p&gt;

&lt;p&gt;For test fixtures, domains such as &lt;code&gt;example.com&lt;/code&gt; are much safer:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;maria.schmidt@example.com
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;They clearly communicate that the address is test data and avoid accidentally involving real users.&lt;/p&gt;

&lt;h2&gt;
  
  
  Make test datasets reproducible
&lt;/h2&gt;

&lt;p&gt;Random data is useful for exploration.&lt;/p&gt;

&lt;p&gt;Repeatable data is useful for debugging.&lt;/p&gt;

&lt;p&gt;Suppose a test fails only when a particular dataset is generated. If every execution creates completely different values, reproducing the problem becomes harder.&lt;/p&gt;

&lt;p&gt;A seeded generator solves this.&lt;/p&gt;

&lt;p&gt;Conceptually:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;seed = checkout-regression-42
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the same generator configuration and seed can reproduce the same dataset.&lt;/p&gt;

&lt;p&gt;This is especially useful for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;regression tests&lt;/li&gt;
&lt;li&gt;imports&lt;/li&gt;
&lt;li&gt;API fixtures&lt;/li&gt;
&lt;li&gt;UI snapshots&lt;/li&gt;
&lt;li&gt;bug reproduction&lt;/li&gt;
&lt;li&gt;CI pipelines&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use random datasets when you want variation.&lt;/p&gt;

&lt;p&gt;Use seeded datasets when you want repeatability.&lt;/p&gt;

&lt;h2&gt;
  
  
  Test boundaries, not just happy paths
&lt;/h2&gt;

&lt;p&gt;Synthetic data becomes much more valuable when you stop treating it as filler.&lt;/p&gt;

&lt;p&gt;Instead, design datasets around scenarios.&lt;/p&gt;

&lt;p&gt;For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Scenario 1: normal signup
Scenario 2: very long name
Scenario 3: missing optional address field
Scenario 4: minimum allowed number
Scenario 5: maximum allowed number
Scenario 6: leap-day date
Scenario 7: duplicate identifier
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The best test dataset is rarely the largest one.&lt;/p&gt;

&lt;p&gt;It is the dataset that deliberately exercises the assumptions in your application.&lt;/p&gt;

&lt;h2&gt;
  
  
  Structured identifiers need special handling
&lt;/h2&gt;

&lt;p&gt;Some values have rules beyond simple formatting.&lt;/p&gt;

&lt;p&gt;Examples include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;UUIDs&lt;/li&gt;
&lt;li&gt;IBANs&lt;/li&gt;
&lt;li&gt;card-number formats&lt;/li&gt;
&lt;li&gt;IMEI numbers&lt;/li&gt;
&lt;li&gt;MAC addresses&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For these, a random string with the right length is often not enough.&lt;/p&gt;

&lt;p&gt;A UUID should follow the appropriate UUID format.&lt;/p&gt;

&lt;p&gt;An IBAN used to test a validator may need the correct country structure and checksum.&lt;/p&gt;

&lt;p&gt;A card-number fixture may need to satisfy the Luhn algorithm.&lt;/p&gt;

&lt;p&gt;That still does &lt;strong&gt;not&lt;/strong&gt; mean the generated value represents a real account, device or payment method.&lt;/p&gt;

&lt;p&gt;Format validity and real-world existence are two completely different things.&lt;/p&gt;

&lt;h2&gt;
  
  
  Generate only the fields you need
&lt;/h2&gt;

&lt;p&gt;Another mistake is generating huge fake profiles for every test.&lt;/p&gt;

&lt;p&gt;If you're testing an import with these columns:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;customer_name
email
order_total
status
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;you probably don't need:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;phone
street
company
job_title
iban
username
date_of_birth
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Smaller datasets are easier to understand and debug.&lt;/p&gt;

&lt;p&gt;A schema-first approach works well:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"customer"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"fullName"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"email"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"total"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"decimal"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"type"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"choice"&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Generate the minimum dataset that exercises the behavior you want to test.&lt;/p&gt;

&lt;h2&gt;
  
  
  Automate test-data generation when it makes sense
&lt;/h2&gt;

&lt;p&gt;Manual generators are useful while developing and exploring.&lt;/p&gt;

&lt;p&gt;Once a test-data workflow becomes repetitive, an API can be more practical.&lt;/p&gt;

&lt;p&gt;For example, a profile request could look like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;curl &lt;span class="nt"&gt;--request&lt;/span&gt; POST &lt;span class="s2"&gt;"https://genory.dev/api/profile"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Authorization: Bearer &lt;/span&gt;&lt;span class="nv"&gt;$GENORY_API_KEY&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--header&lt;/span&gt; &lt;span class="s2"&gt;"Content-Type: application/json"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--data&lt;/span&gt; &lt;span class="s1"&gt;'{
    "country": "DE",
    "amount": 1,
    "fields": ["firstName", "lastName", "email"]
  }'&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now a fixture can be generated from a script, CI job or development tool instead of being copied manually.&lt;/p&gt;

&lt;p&gt;Whatever service you use, keep API keys in environment variables or a secret manager rather than committing them to your repository.&lt;/p&gt;

&lt;h2&gt;
  
  
  A practical workflow
&lt;/h2&gt;

&lt;p&gt;A simple process works surprisingly well:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Define the behavior you want to test.&lt;/li&gt;
&lt;li&gt;Decide which fields actually matter.&lt;/li&gt;
&lt;li&gt;Choose the country or format constraints.&lt;/li&gt;
&lt;li&gt;Add edge cases intentionally.&lt;/li&gt;
&lt;li&gt;Use synthetic rather than production data.&lt;/li&gt;
&lt;li&gt;Use a seed when reproducibility matters.&lt;/li&gt;
&lt;li&gt;Generate a small dataset first.&lt;/li&gt;
&lt;li&gt;Scale only when the small test works.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For quick experiments, you can build synthetic profiles and custom datasets with &lt;a href="https://genory.dev/tools/test-data" rel="noopener noreferrer"&gt;Genory&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Genory includes a &lt;a href="https://genory.dev/generate" rel="noopener noreferrer"&gt;Test Data Generator&lt;/a&gt;, schema-based dataset tools, UUID utilities and format-specific generators.&lt;/p&gt;

&lt;p&gt;If you're automating the process, the current API reference is available in the &lt;a href="https://genory.dev/docs" rel="noopener noreferrer"&gt;Genory developer documentation&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Final thought
&lt;/h2&gt;

&lt;p&gt;Good test data isn't data that looks impressive.&lt;/p&gt;

&lt;p&gt;It's data that exposes assumptions.&lt;/p&gt;

&lt;p&gt;Synthetic data gives developers a way to build realistic fixtures without turning production customer information into development material.&lt;/p&gt;

&lt;p&gt;Generate less data, make it intentional, and design every dataset around the behavior you're actually trying to test.&lt;/p&gt;

</description>
      <category>testing</category>
      <category>webdev</category>
      <category>api</category>
      <category>programming</category>
    </item>
  </channel>
</rss>
