<?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: Graham Sutton</title>
    <description>The latest articles on DEV Community by Graham Sutton (@grahamsutton).</description>
    <link>https://dev.to/grahamsutton</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%2F174773%2Ff1d2d024-9554-411a-b9c6-49da92cb2d51.jpg</url>
      <title>DEV Community: Graham Sutton</title>
      <link>https://dev.to/grahamsutton</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/grahamsutton"/>
    <language>en</language>
    <item>
      <title>Mockyard Update: Real Addresses Are Here</title>
      <dc:creator>Graham Sutton</dc:creator>
      <pubDate>Thu, 18 Jun 2026 21:48:06 +0000</pubDate>
      <link>https://dev.to/grahamsutton/mockyard-update-real-addresses-are-here-hg5</link>
      <guid>https://dev.to/grahamsutton/mockyard-update-real-addresses-are-here-hg5</guid>
      <description>&lt;p&gt;Quick update on &lt;a href="https://github.com/portside-labs/mockyard" rel="noopener noreferrer"&gt;Mockyard&lt;/a&gt; - the free, open source, self-hostable alternative to Mockaroo I wrote about &lt;a href="https://dev.to/grahamsutton/i-made-a-free-open-source-self-hostable-alternative-to-mockaroo-3oo5"&gt;a few weeks ago&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Problem With Fake Addresses
&lt;/h2&gt;

&lt;p&gt;I needed to test a CASS certification pipeline, which validates whether addresses are real and deliverable. Fake addresses fail that check immediately, so they were useless for testing.&lt;/p&gt;

&lt;p&gt;I also didn't want residential addresses. If a bug ever slipped through and triggered a real mail piece, I didn't want it landing at someone's house. Non-residential addresses meant real, valid data without any of that risk.&lt;/p&gt;

&lt;h2&gt;
  
  
  Real Addresses, Now Built In
&lt;/h2&gt;

&lt;p&gt;Mockyard now ships with &lt;strong&gt;100,000+ real, non-residential US addresses&lt;/strong&gt; you can generate against directly.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkya3wcqlb96577gjf9eb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkya3wcqlb96577gjf9eb.png" alt="Screenshot of Mockyard with Real Address user interface" width="800" height="619"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When you select the &lt;strong&gt;Real Address&lt;/strong&gt; type, Mockyard maps each component - &lt;code&gt;address_line_1&lt;/code&gt;, &lt;code&gt;address_line_2&lt;/code&gt;, &lt;code&gt;city&lt;/code&gt;, &lt;code&gt;state&lt;/code&gt;, &lt;code&gt;country&lt;/code&gt;, and &lt;code&gt;zip&lt;/code&gt; - to separate columns automatically. You can rename any of them to match your schema.&lt;/p&gt;

&lt;p&gt;You also get optional filters if you need to scope the data down:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;States&lt;/strong&gt; (e.g. &lt;code&gt;CA, NY, TX&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cities&lt;/strong&gt; (e.g. &lt;code&gt;San Francisco, Austin&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zips&lt;/strong&gt; (e.g. &lt;code&gt;10001, 90210&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Countries&lt;/strong&gt; (just &lt;code&gt;US&lt;/code&gt; for now)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The candidate pool updates in real time as you adjust filters.&lt;/p&gt;

&lt;h2&gt;
  
  
  A Few Notes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;US only for now.&lt;/strong&gt; I'll add more countries if there's demand - open an issue on the repo if that's useful to you.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Non-residential only.&lt;/strong&gt; These aren't people's home addresses.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;All rows unique — unless you filter.&lt;/strong&gt; With no filters applied, all 100K addresses are available and all 100,000 rows will be unique. Filtering reduces the candidate pool, so if the number of candidates drops below the number of rows you're generating, addresses will start to repeat.&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;Repository: &lt;a href="https://github.com/portside-labs/mockyard" rel="noopener noreferrer"&gt;https://github.com/portside-labs/mockyard&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As always, if you find it useful or want something added, open an issue. That's the fastest way to get it prioritized.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>testing</category>
    </item>
    <item>
      <title>I made a free, open source, self-hostable alternative to Mockaroo</title>
      <dc:creator>Graham Sutton</dc:creator>
      <pubDate>Wed, 13 May 2026 15:47:20 +0000</pubDate>
      <link>https://dev.to/grahamsutton/i-made-a-free-open-source-self-hostable-alternative-to-mockaroo-3oo5</link>
      <guid>https://dev.to/grahamsutton/i-made-a-free-open-source-self-hostable-alternative-to-mockaroo-3oo5</guid>
      <description>&lt;p&gt;I created &lt;a href="https://github.com/portside-labs/mockyard?utm_source=chatgpt.com" rel="noopener noreferrer"&gt;Mockyard&lt;/a&gt; - a free, open source, and self-hostable alternative to Mockaroo.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft794d5um4c4cuuz0t1r1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ft794d5um4c4cuuz0t1r1.png" alt="Screenshot of Mockyard" width="800" height="440"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Mockyard ships as a Docker container that just runs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;docker run &lt;span class="nt"&gt;-p&lt;/span&gt; 8080:8080 ghcr.io/portside-labs/mockyard
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Problem
&lt;/h1&gt;

&lt;p&gt;If you don't know what Mockaroo is, it's an online tool for generating large amounts of mock data in formats like CSV, JSON, SQL, etc.&lt;/p&gt;

&lt;p&gt;The catch is that Mockaroo is limited to &lt;strong&gt;1K rows per file on the free tier&lt;/strong&gt;, and costs &lt;strong&gt;$60/year&lt;/strong&gt; if you want to generate files with up to &lt;strong&gt;100K rows&lt;/strong&gt;. It's also &lt;strong&gt;not open source&lt;/strong&gt; and &lt;strong&gt;not self-hostable&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;I built Mockyard for two reasons:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;AI has made it possible to build things that used to live in the "I wish I had time for this" category.&lt;/li&gt;
&lt;li&gt;I needed to test CSV ingestion pipelines with &lt;strong&gt;hundreds of thousands to millions of records&lt;/strong&gt;, and I wanted something that was &lt;strong&gt;fast, memory efficient, easy to use, and didn't require going online or installing a bunch of languages, tools, or packages&lt;/strong&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Now it costs me $0 to generate up to 10 million rows per file, every day of the year.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Honestly, I figured someone would have already built this, but either nobody actually has or I'm terrible at Googling.&lt;/p&gt;

&lt;p&gt;And yes, I tried generatedata.com too. It's good, but it didn't quite fit the way I needed to generate some of my mock data.&lt;/p&gt;

&lt;h1&gt;
  
  
  Differences
&lt;/h1&gt;

&lt;p&gt;One thing I wanted was the ability to generate data using &lt;strong&gt;weighted enums&lt;/strong&gt;. In Mockyard, you can specify not just fixed enum values, but also their distribution.&lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;20% of records should have &lt;code&gt;role = Admin&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;30% should have &lt;code&gt;role = Manager&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;The remaining 50% should have &lt;code&gt;role = Viewer&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Another issue I had was address realism. Seeing things like:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Miami, Yukon Territory, Switzerland&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;for city, state, and country combinations hurt my eyes.&lt;/p&gt;

&lt;p&gt;So Mockyard supports &lt;strong&gt;lookup tables&lt;/strong&gt; so fields can stay logically connected. If a city is selected, the state and country can match appropriately instead of being generated independently and producing nonsense.&lt;/p&gt;

&lt;p&gt;You still have to specify your own lookup values, but at least the generated data looks realistic.&lt;/p&gt;

&lt;h1&gt;
  
  
  Performance
&lt;/h1&gt;

&lt;p&gt;Initial benchmarks for the same CSV with four columns:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Rows&lt;/th&gt;
&lt;th&gt;Format&lt;/th&gt;
&lt;th&gt;Time&lt;/th&gt;
&lt;th&gt;Throughput (rows/sec)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1,000&lt;/td&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;0.02s&lt;/td&gt;
&lt;td&gt;~50,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000&lt;/td&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;0.09s&lt;/td&gt;
&lt;td&gt;~111,111&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;0.53s&lt;/td&gt;
&lt;td&gt;~188,679&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;4.89s&lt;/td&gt;
&lt;td&gt;~204,499&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000,000&lt;/td&gt;
&lt;td&gt;CSV&lt;/td&gt;
&lt;td&gt;53.61s&lt;/td&gt;
&lt;td&gt;~186,532&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;10 million rows is currently the max in Mockyard.&lt;/p&gt;

&lt;p&gt;Anything beyond one million rows and Excel won't even load the whole file anyway (at least on Mac), so this should cover most real-world scenarios.&lt;/p&gt;

&lt;h1&gt;
  
  
  Web or API - Your Pick
&lt;/h1&gt;

&lt;p&gt;If you want to generate data programmatically, Mockyard also exposes an API endpoint:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4d6yx9oc7jvwnettfgg.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fo4d6yx9oc7jvwnettfgg.png" alt="Screenshot of the OpenAPI spec" width="800" height="644"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The UI actually uses the exact same API under the hood.&lt;/p&gt;

&lt;h1&gt;
  
  
  Output
&lt;/h1&gt;

&lt;p&gt;Right now, output is limited to &lt;strong&gt;CSV and JSON&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;p&gt;Because I personally haven't needed anything else yet.&lt;/p&gt;

&lt;p&gt;That said, if people actually find this useful and want support for additional formats, feel free to open an issue on the repo.&lt;/p&gt;

&lt;p&gt;Repository: &lt;a href="https://github.com/portside-labs/mockyard" rel="noopener noreferrer"&gt;https://github.com/portside-labs/mockyard&lt;/a&gt;&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>productivity</category>
      <category>opensource</category>
      <category>testing</category>
    </item>
    <item>
      <title>Raw SQL Migrations Library</title>
      <dc:creator>Graham Sutton</dc:creator>
      <pubDate>Fri, 13 Sep 2019 21:38:14 +0000</pubDate>
      <link>https://dev.to/grahamsutton/raw-sql-migrations-library-3a1h</link>
      <guid>https://dev.to/grahamsutton/raw-sql-migrations-library-3a1h</guid>
      <description>&lt;p&gt;Where I currently work, we operate on a stack of mostly PHP and PostgreSQL. Our framework was written in ZF1 (it's legacy), and our deployment process for keeping our database changes version-controlled is quite tedious and complex.&lt;/p&gt;

&lt;p&gt;Outside of work, I love using frameworks like Laravel and Rails and one of the features I really love from both of these is migrations. Since our legacy application at work doesn't have this concept, I started thinking of ways to take this modern approach and apply it to our legacy app.&lt;/p&gt;

&lt;p&gt;Since we cannot convert our entire application over to one of these frameworks (it would be a major overhaul), I looked into some options like Phinx and Flyway for possible integration, but these options were not really compatible with our app (for various reasons that would deserve their own post).&lt;/p&gt;

&lt;p&gt;At our company, we make very heavy use of PostgreSQL: complex procedures, triggers, views, multiple schemas, data warehousing, etc... we power everything on it. Many migration-type libraries usually have some abstraction layer that doesn't really support the full range of these database features. For example, Rails migrations are written in Ruby and then converted down to SQL before execution; same with Laravel and PHP. This isn't a bad thing, but these types of abstractions don't truly support the wide range of database features (particularly procedures) and are typically limited to just creating tables, indexes, and constraints.&lt;/p&gt;

&lt;p&gt;So, I decided to task myself (for fun mostly) with trying to build a migrations library that would run on raw SQL, and lo and behold, I actually got a simple concept going! The underlying CLI is written in PHP, but you write and execute migrations in raw SQL.&lt;/p&gt;

&lt;p&gt;I figured that maybe a lot of other people could get some use from such a library, and so I put it up on GitHub a while back but never really shared its existence with anyone. So today, that is what I am doing.&lt;/p&gt;

&lt;p&gt;I am really looking for people who would like to help make it better. I think it's a good start, but I know a truly great tool isn't built by one person alone. Feel free to criticize, praise, or contribute!&lt;/p&gt;

&lt;p&gt;Exodus Migrations Library: &lt;a href="https://github.com/grahamsutton/exodus" rel="noopener noreferrer"&gt;https://github.com/grahamsutton/exodus&lt;/a&gt;&lt;/p&gt;

</description>
      <category>php</category>
      <category>sql</category>
      <category>database</category>
    </item>
    <item>
      <title>Laravel's factory method, but for JavaScript.</title>
      <dc:creator>Graham Sutton</dc:creator>
      <pubDate>Sun, 02 Jun 2019 14:40:08 +0000</pubDate>
      <link>https://dev.to/grahamsutton/laravel-s-factory-method-but-for-javascript-1o3a</link>
      <guid>https://dev.to/grahamsutton/laravel-s-factory-method-but-for-javascript-1o3a</guid>
      <description>&lt;p&gt;When I became exhausted with trying to create tons of mock API data on the fly for my Node projects, I created a simple little script that would let me define the skeleton of the JSON structure I wanted without having to copy, paste, and modify each individual record.&lt;/p&gt;

&lt;p&gt;This script is now available as an NPM package that does almost exactly what Laravel's factory method does except for JavaScript. It's lightweight and great for stubbing APIs in your Vue and React projects, too!&lt;/p&gt;

&lt;p&gt;Link to the repo: &lt;a href="https://github.com/grahamsutton/factory" rel="noopener noreferrer"&gt;https://github.com/grahamsutton/factory&lt;/a&gt;&lt;/p&gt;

</description>
      <category>javascript</category>
      <category>react</category>
      <category>vue</category>
      <category>webdev</category>
    </item>
  </channel>
</rss>
