<?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: Andrei</title>
    <description>The latest articles on DEV Community by Andrei (@anivan).</description>
    <link>https://dev.to/anivan</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%2F3922395%2F4758cc29-3c5f-4962-8029-e5a312af7f18.png</url>
      <title>DEV Community: Andrei</title>
      <link>https://dev.to/anivan</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/anivan"/>
    <language>en</language>
    <item>
      <title>Lean System Design: URL Shortener</title>
      <dc:creator>Andrei</dc:creator>
      <pubDate>Tue, 23 Jun 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/anivan/lean-system-design-url-shortener-im8</link>
      <guid>https://dev.to/anivan/lean-system-design-url-shortener-im8</guid>
      <description>&lt;p&gt;Hey!&lt;/p&gt;

&lt;p&gt;As I wrote in the &lt;a href="https://saneengineer.com/posts/2026-01-15-lean-system-design/index.html" rel="noopener noreferrer"&gt;previous post&lt;/a&gt;, I became really interested in &lt;strong&gt;Lean System Design&lt;/strong&gt; – real-life system design, not forced to satisfy Google-scale requirements.&lt;/p&gt;

&lt;p&gt;Today, I want to review a classic example of a system design interview question – URL Shortener.&lt;/p&gt;

&lt;p&gt;The task is simple – we need to design an application that converts long URLs to short ones, which can then be used for redirects to the original URLs. The goal is to have a short URL that can be easily shared as text or a readable QR code.&lt;/p&gt;

&lt;p&gt;Common examples of such services are &lt;a href="https://bitly.com/" rel="noopener noreferrer"&gt;Bitly&lt;/a&gt; and &lt;a href="https://tinyurl.com/" rel="noopener noreferrer"&gt;TinyURL&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So we have just two user cases here: creating a tiny URL and opening a tiny URL.&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%2Fbzb9vlloed35qcgd6wpp.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%2Fbzb9vlloed35qcgd6wpp.png" alt="Submit long URL and receive a short URL" width="797" height="108"&gt;&lt;/a&gt;&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%2F7lxez91hha4re1otwrtp.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%2F7lxez91hha4re1otwrtp.png" alt="Open short URL and be redirected to the long URL" width="797" height="88"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And of course, we have non-functional requirements. Let's use a popular book by &lt;strong&gt;Alex Xu, System Design Interview&lt;/strong&gt;, as a reference for what these requirements are and the canonical expected interview solution for this task.&lt;/p&gt;

&lt;h1&gt;
  
  
  Requirements
&lt;/h1&gt;

&lt;p&gt;Interview requirements:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 million URLs generated per day&lt;/li&gt;
&lt;li&gt;The resulting URLs should be as short as possible &lt;/li&gt;
&lt;li&gt;High availability, *&lt;strong&gt;&lt;em&gt;scalability&lt;/em&gt;&lt;/strong&gt;*, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And we have some assumptions we can make out of these requirements to have a better understanding of numbers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;100 million URLs per day is about &lt;strong&gt;1160 writes per second&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;We assume the read-to-write ratio is 10:1, so we'll have &lt;strong&gt;11600 reads per second&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;We assume our service will run for 10 years, so we'll have 365 billion records, and having an average URL length of 100 chars, we'll need 365 TB of storage&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;OK, looks solid.&lt;/p&gt;

&lt;p&gt;But are these requirements and assumptions &lt;strong&gt;realistic&lt;/strong&gt;?&lt;/p&gt;

&lt;p&gt;Let's see what we know about the biggest players on the market – Bitly and TinyURL.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Bitly, on their &lt;a href="https://bitly.com/" rel="noopener noreferrer"&gt;main page&lt;/a&gt;, says they have 256M Links &amp;amp; QR Codes created monthly&lt;/li&gt;
&lt;li&gt;Bitly in 2022 had 5.7M monthly active users and 500K+ customers, according to their &lt;a href="https://bitly.com/pages/resources/press/bitly-wraps-2022-surpassing-100m-in-arr-and-over-500k-global-customers/" rel="noopener noreferrer"&gt;press release&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Bitly also says in the same press release that they have &lt;em&gt;"10 Billion+ Clicks and QR Code Scans Every Month"&lt;/em&gt;
&lt;/li&gt;
&lt;li&gt;TinyURL &lt;a href="https://tinyurl.com/app/pricing" rel="noopener noreferrer"&gt;says&lt;/a&gt; it's trusted by ~3.9M users&lt;/li&gt;
&lt;li&gt;TinyURL &lt;a href="https://tinyurl.com/app/about-us" rel="noopener noreferrer"&gt;has&lt;/a&gt; created 30 billion short URLs over 23 years&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What can we see here? Well, first of all, the biggest player on the market – Bitly – has just 256M URLs created monthly. That's only 8 million URLs generated per day. And they also have only 330 million redirects per day.&lt;/p&gt;

&lt;p&gt;And these numbers convert to:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;93 writes per second&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;3820 reads per second&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  What RDS instance do you actually need?
&lt;/h2&gt;

&lt;p&gt;Your PostgreSQL RPS depends on whether your working set fits in RAM. I benchmarked every major RDS size to find that threshold for each – with measured RPS, latency, and cost per 1k requests by workload type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://saneengineer.com/postgres-cheat-sheet/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=postgres-cheat-sheet" rel="noopener noreferrer"&gt;Get PostgreSQL Sizing Cheat Sheet here.&lt;/a&gt;&lt;/p&gt;




&lt;p&gt;So, &lt;strong&gt;the biggest player&lt;/strong&gt; on the market, whose scale, from a business perspective, I believe is problematic to achieve, &lt;strong&gt;has a noticeably smaller load&lt;/strong&gt; than is required for the task. If you want to build something similar in your company, your scale will probably be even smaller than that.&lt;/p&gt;

&lt;p&gt;!&amp;gt; It's important to note here that there are services that use short URLs basically for anything, like Twitter/X. They shorten any URL any user posts, and they are probably the biggest player here, but this is an internal feature, and they don't share usage statistics, so I can't use it here for comparison. Also, you are usually not forced to shorten any URL your system sees. Twitter is a bit special, and there is no big reason to follow their decision.&lt;/p&gt;

&lt;h1&gt;
  
  
  Interview System Design
&lt;/h1&gt;

&lt;p&gt;How can we design such a system?&lt;/p&gt;

&lt;p&gt;There are two classical solutions to this, both described in Alex Xu's book:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Use hashing for long URLs, insert them into a relational DB, and retry in case of collisions (with appending the hashing result again and again if needed)&lt;/li&gt;
&lt;li&gt;Use a distributed unique ID generator, and convert these IDs to Base62&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both of these options use a fixed-length ID to support the maximum number of URLs that can be generated (over 10 years) and to keep short URLs short.&lt;/p&gt;

&lt;p&gt;I agree that both will work, and they are good answers for the system design interview nowadays. But what is not perfect in these options?&lt;/p&gt;

&lt;h2&gt;
  
  
  Hashing
&lt;/h2&gt;

&lt;p&gt;The known issue with this option is that you need to check whether the hash is already in use. To do this efficiently, you will need an index on your DB. The ideal index here is something with a &lt;a href="https://en.wikipedia.org/wiki/Bloom_filter" rel="noopener noreferrer"&gt;bloom filter&lt;/a&gt; – a probabilistic data structure which allows you to check if some element is definitely not in the set (or there is a chance it is in the set). However, a B-tree index will obviously work here as well. &lt;/p&gt;

&lt;p&gt;So, we can speed up the check if the hash is already in use using the index. But at the same time, DB will need to maintain this index, which will decrease insert speed.&lt;/p&gt;

&lt;h2&gt;
  
  
  Distributed Unique ID Generator
&lt;/h2&gt;

&lt;p&gt;The Distributed Unique ID Generator option isn't that bad. We want to use an ID generator here that reduces the chance of ID collisions in a distributed system to zero or nearly zero. One option is to use &lt;a href="https://en.wikipedia.org/wiki/Snowflake_ID" rel="noopener noreferrer"&gt;Snowflake ID&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;With this option, you don't need to pay a lot of attention to collisions or maintaining your index. And this is a good direction if you &lt;strong&gt;really&lt;/strong&gt; need to scale. But let's see what we can achieve without going distributed.&lt;/p&gt;

&lt;h1&gt;
  
  
  Real-World Design
&lt;/h1&gt;

&lt;p&gt;As we saw, in the real world, we need to support just up to 100 writes per second and up to 4k reads per second. Both numbers look more than achievable on a single machine with a canonical DB.&lt;/p&gt;

&lt;p&gt;I have vibecoded a simple solution in Go that uses either SQLite or PostgreSQL to demonstrate the possibilities of a single machine here.&lt;/p&gt;

&lt;p&gt;We will not use hashing; we will use only a primary auto-incremental ID, which is encoded to Base64URL. So, this is a non-distributed version of the canonical solution #2.&lt;/p&gt;

&lt;p&gt;To test the solution, I used my home server with a NAS motherboard and an Intel Celeron N5105 (which is very far from high-tier hardware, and it cost me like 150 EUR on AliExpress) and some HDD (not even an SSD).&lt;/p&gt;

&lt;p&gt;I've also simulated a pre-filled DB with 3 billion records, which is the expected DB size after 1 year of service usage.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./dbgen &lt;span class="nt"&gt;-type&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;sqlite &lt;span class="nt"&gt;-count&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;3000000000
&lt;span class="go"&gt;
Total records: 3,000,000,000
Total time:    1h26m48s
Avg rate:      576,035 records/s
File size:     438.66 GB
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And, if we check the results, they will be more than acceptable.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./loadtest &lt;span class="nt"&gt;-duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60s &lt;span class="nt"&gt;-concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50
&lt;span class="go"&gt;
=== URL Creation ===
Total Requests:  152412
Successful:      152412
Failed:          0
RPS:             2540.20 req/s

=== Redirect ===
Total Requests:  952170
Successful:      952170
Failed:          0
RPS:             15869.50 req/s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;So, we have like &lt;strong&gt;2540 writes per second&lt;/strong&gt; and &lt;strong&gt;15869 reads per second&lt;/strong&gt;, which is enough not only for our realistic requirements, but also for the original interview requirements. And that's on my cheap, bizarre hardware.&lt;/p&gt;

&lt;p&gt;All the scripts for data generation and load testing are available in the repo, so you can make these experiments yourself: &lt;a href="https://github.com/anivaniuk/small-shortener" rel="noopener noreferrer"&gt;GitHub Repo&lt;/a&gt;.&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%2F3xo2snax28wkxattwk3t.jpeg" 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%2F3xo2snax28wkxattwk3t.jpeg" alt="My NAS used for this test." width="800" height="600"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Availability
&lt;/h2&gt;

&lt;p&gt;As we use a single machine setup, we have perfect consistency, but what about availability? If our machine goes down, our service will not be operational until it is back online.&lt;/p&gt;

&lt;p&gt;But how bad is that?&lt;/p&gt;

&lt;p&gt;If we analyse Bitly SLAs, we'll see that on their Enterprise plan (they don't give any guarantees on other plans), they promise 99.9% availability. That's &lt;a href="https://uptime.is/" rel="noopener noreferrer"&gt;43m 50s&lt;/a&gt; of downtime per month. That's quite a lot!&lt;/p&gt;

&lt;p&gt;There are two main reasons why you usually may have downtime in your system: deployments and incidents.&lt;/p&gt;

&lt;p&gt;Deployments are usually straightforward, and you can replace binaries on the machine quite fast. If you don't have a long warm-up for your service, it's a matter of seconds. And I can't find any reason why the described URL shortener should have any warm-up. The example that I demonstrate and test doesn't use any caching or anything besides a lightweight wrapper around a DB.&lt;/p&gt;

&lt;p&gt;It's more problematic when you want to migrate data during the downtime, but you probably don't want to. Even in a non-distributed world, it's better to avoid incompatible changes, and this shouldn't really be a big problem if you understand how to make compatible changes. And with compatible changes, you can migrate your data while your system is running.&lt;/p&gt;

&lt;p&gt;For incidents, it's more complicated. You can never predict whether you will have an incident tomorrow, and you can't control their duration. It may depend heavily on your code quality, your processes, and many other factors. But it's important to remember that going distributed is not a silver bullet. Even with redundancy, you may still experience downtime for other reasons. And &lt;strong&gt;some of these reasons might be related to the fact that you went distributed&lt;/strong&gt; and introduced this redundancy (due to an increased number of moving parts, greater complexity, etc.).&lt;/p&gt;

&lt;h2&gt;
  
  
  First Steps of Scaling
&lt;/h2&gt;

&lt;p&gt;Still, I agree: making simple, stateless applications that scale horizontally is a cheap way to improve our scalability and availability. It's a step up in complexity, but it is not that bad, since our app is stateless, and this doesn't require any complex distributed connections.&lt;/p&gt;

&lt;p&gt;So, let's switch our application from SQLite to PostgreSQL and check the performance.&lt;/p&gt;

&lt;p&gt;A lot of cloud providers offer PostgreSQL at a reasonable price and reasonable availability guarantees (like Multi-AZ in AWS), and it provides a lot of functionality to you, so it's usually a good default choice, but technically, you could use any other relational DB.&lt;/p&gt;

&lt;p&gt;What we are doing here is &lt;strong&gt;delegating&lt;/strong&gt; the complexity of distributed systems to a &lt;strong&gt;well-matched tool that is solid, mature, well-represented on the market&lt;/strong&gt;, and that gives us what we need. We basically build our system around this technology.&lt;/p&gt;

&lt;h3&gt;
  
  
  PostgreSQL
&lt;/h3&gt;

&lt;p&gt;In order to test PostgreSQL version, I've used &lt;code&gt;c7i.large&lt;/code&gt; EC2 instance, and PostgreSQL instance on &lt;code&gt;db.r8g.large&lt;/code&gt; via RDS. I've also used IO2 disk with baseline IOPS for our DB.&lt;/p&gt;

&lt;p&gt;The results of the same experiment are the following.&lt;/p&gt;

&lt;p&gt;No Multi-AZ case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./loadtest &lt;span class="nt"&gt;-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:3000 &lt;span class="nt"&gt;-duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60s &lt;span class="nt"&gt;-concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50
&lt;span class="go"&gt;
=== URL Creation ===
Total Requests:  954455
Successful:      954455
Failed:          0
RPS:             15907.58 req/s

=== Redirect ===
Total Requests:  1474310
Successful:      1474310
Failed:          0
RPS:             24571.83 req/s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Multi-AZ case:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight console"&gt;&lt;code&gt;&lt;span class="gp"&gt;$&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;./loadtest &lt;span class="nt"&gt;-url&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;http://localhost:3000 &lt;span class="nt"&gt;-duration&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;60s &lt;span class="nt"&gt;-concurrency&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;50
&lt;span class="go"&gt;
=== URL Creation ===
Total Requests:  881595
Successful:      881595
Failed:          0
RPS:             14693.25 req/s

=== Redirect ===
Total Requests:  1575232
Successful:      1575232
Failed:          0
RPS:             26253.87 req/s
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This option doesn't use any sharding. It's basically a single DB with an additional stand-by instance to improve availability. Still, it performs well.&lt;/p&gt;

&lt;p&gt;The total cost of this AWS solution is approximately USD 750 per month, which should be more than affordable if you want to compete with Bitly. And you can definitely go cheaper by adjusting the hardware to your actual load.&lt;/p&gt;

&lt;p&gt;Below are charts showing write and read RPS for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;PostgreSQL solution hosted on AWS&lt;/li&gt;
&lt;li&gt;SQLite solution hosted on my NAS&lt;/li&gt;
&lt;li&gt;Interview requirements&lt;/li&gt;
&lt;li&gt;Real-world requirements&lt;/li&gt;
&lt;/ul&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%2Fny018ta291xqw7sx64et.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%2Fny018ta291xqw7sx64et.png" alt="Performance of solutions and requirements." width="800" height="531"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, our lean design shows performance that easily satisfies both interview and real-world requirements.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;p&gt;Of course, such classical problems, like URL Shortener, are just an instrument in interviews to provoke further discussions and check how candidates approach system design. But isn't it remarkable that people are trained to answer such kinds of questions, overcomplicating everything?&lt;/p&gt;

&lt;p&gt;As you may see, there is a lot of freedom in how to solve that. And you can pick a straightforward solution that will be performant enough to beat the biggest players on the market.&lt;/p&gt;

&lt;p&gt;And of course, in some cases, this simple PostgreSQL setup will not be enough, and we'll need to scale further and adopt a different design, probably with some sharding. But how can we check if single-machine Postgres is enough? I've prepared a benchmark and a Cheat Sheet on PostgreSQL performance across different AWS instance types ⬇️&lt;/p&gt;

&lt;p&gt;&lt;a href="https://saneengineer.com/postgres-cheat-sheet/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=postgres-cheat-sheet" rel="noopener noreferrer"&gt;Get PostgreSQL Sizing Cheat Sheet here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>microservices</category>
      <category>programming</category>
      <category>architecture</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Lean System Design</title>
      <dc:creator>Andrei</dc:creator>
      <pubDate>Tue, 12 May 2026 12:00:00 +0000</pubDate>
      <link>https://dev.to/anivan/lean-system-design-km7</link>
      <guid>https://dev.to/anivan/lean-system-design-km7</guid>
      <description>&lt;p&gt;Hey!&lt;/p&gt;

&lt;p&gt;Over the past year, I became interested in a systematic approach to system design. It appeared to be a quite overused term nowadays – it includes pure and in-depth knowledge about technological systems; it includes how to use them and how to build new systems out of existing ones in real life; and it also includes the "system design interview" area, which is somehow different from the first two points.&lt;/p&gt;

&lt;p&gt;Eventually, I've also realised there is a strong push in the community toward building complex distributed systems. This is mainly driven by large tech companies, which need to scale their products to millions and millions of users. So, they require this approach of thinking in their interviews, they popularise it at conferences and in the tools they develop.&lt;/p&gt;

&lt;p&gt;The problem is that you probably don't work at Google, and &lt;strong&gt;your system will never need to handle Google-scale traffic&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Distributed systems are complex, and applying approaches popularised by big tech companies might be harmful to most other companies. It could be harmful in terms of cost, development velocity, and maintainability.&lt;/p&gt;

&lt;p&gt;Over my 13 years in engineering, I've seen many complex distributed systems that engineering teams built over months, only to be decommissioned shortly after release for business reasons. And I've also seen systems that became so unnecessarily complicated that maintaining them took up 80% of engineers' time.&lt;/p&gt;

&lt;p&gt;I feel we need to address these concerns with something I'd call &lt;strong&gt;Lean System Design&lt;/strong&gt;.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Lean System Design&lt;/strong&gt; is the design of systems to meet explicit requirements with minimal complexity: measurable requirements, system-lifetime-aware decisions, long-term cost efficiency, and operational simplicity.&lt;/p&gt;
&lt;/blockquote&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%2F7norcmk2snm0qu0ngaqk.jpeg" 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%2F7norcmk2snm0qu0ngaqk.jpeg" alt="The pilgrims resting — Ferdinand Georg Waldmüller" width="800" height="627"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Real-World Requirements
&lt;/h2&gt;

&lt;p&gt;No matter if you work for a big tech company or not, you need to know numbers in order to make decisions on the solutions you build.&lt;/p&gt;

&lt;p&gt;The common issue here is that in big tech, you almost always need proper scalability to support millions of users. And companies outside of big tech frequently don't have internal expertise on &lt;strong&gt;what decisions to make&lt;/strong&gt;. And, following the popularity, they may not choose the best options for their case.&lt;/p&gt;

&lt;p&gt;Real-world systems frequently follow requirements similar to these:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;10 to 1000 RPS, not millions;&lt;/li&gt;
&lt;li&gt;latency and availability targets that aim ordinary users, not some sophisticated SLAs;&lt;/li&gt;
&lt;li&gt;per use-case data correctness guarantees;&lt;/li&gt;
&lt;li&gt;operability and maintainability – it should be easy to diagnose and fix the issues;&lt;/li&gt;
&lt;li&gt;limited infra and people costs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It doesn't look like we need something very complicated to satisfy this, right? So why do people choose distributed?&lt;/p&gt;




&lt;h2&gt;
  
  
  What RDS instance do you actually need?
&lt;/h2&gt;

&lt;p&gt;Your PostgreSQL RPS depends on whether your working set fits in RAM. I benchmarked every major RDS size to find that threshold for each – with measured RPS, latency, and cost per 1k requests by workload type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://saneengineer.com/postgres-cheat-sheet/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=postgres-cheat-sheet" rel="noopener noreferrer"&gt;Get PostgreSQL Sizing Cheat Sheet here.&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Distributed?
&lt;/h2&gt;

&lt;p&gt;Distributed systems are complicated because of their nature. When building such systems (and using existing ones), we need to constantly think about consistency and availability. And there is no single "slider" between consistency and availability that you can select some point on. We have a lot of tools to build distributed systems, and each tool is different: it can be configured differently and will behave differently, with its own issues, problems, and trade-offs. And choosing "distributed", we'll need to handle all these complexities and maintain the resulting system.&lt;/p&gt;

&lt;p&gt;However, after resolving all these issues, we'll achieve what is never possible with a single-machine system – almost infinite &lt;strong&gt;scalability&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;There are also other potential benefits frequently associated with building distributed (in a broad sense) systems, such as better team scalability or clearer domain separation. In my opinion, though, all these reasons are &lt;strong&gt;not that significant&lt;/strong&gt;, and shouldn't be considered in the distributed vs non-distributed question. Teams organisation and domain separation just &lt;strong&gt;accidentally&lt;/strong&gt; happened to be the same discussion because of the popularisation of microservices. These aspects may differ significantly even in a non-distributed world, and shouldn't be that tightly linked.&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%2Fnfpmj9lxzei20c1k9eht.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%2Fnfpmj9lxzei20c1k9eht.png" alt="Each connection in a distributed system is a potential source for consistency and availability issues" width="800" height="516"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Single Machine
&lt;/h2&gt;

&lt;p&gt;OK, so &lt;strong&gt;scalability&lt;/strong&gt;. It is indeed not possible to achieve the same scalability with a single-machine setup. But what are the limits? Let's check the real-life examples.&lt;/p&gt;

&lt;p&gt;Probably, the most popular example is &lt;strong&gt;Stack Overflow&lt;/strong&gt;. In its best years, it had a single database and handled 6k queries per second, running smoothly and delivering low latency. The hardware needed to handle that would now probably cost a couple of thousand USD per month, which is more than affordable for a company of that scale. Also, Stack Overflow is quite large, and most of the systems engineers build will never reach such a scale or load. &lt;a href="https://nickcraver.com/blog/2016/02/17/stack-overflow-the-architecture-2016-edition/" rel="noopener noreferrer"&gt;See more about their architecture&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;GitHub Pages&lt;/strong&gt; is also a noticeable example. Until around 2015, all the GitHub Pages were hosted on a single pair of machines (active + standby) with an nginx config regenerated by a cron job. Straightforward architecture on a single machine that was very efficient for them and supported thousands of requests per second. &lt;a href="https://github.blog/news-insights/the-library/rearchitecting-github-pages/" rel="noopener noreferrer"&gt;See more&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;These are examples of successful companies that served millions of users while maintaining a simple architecture without large distributed systems.&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%2Fsvophfzbhtwmx6h4144k.jpeg" 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%2Fsvophfzbhtwmx6h4144k.jpeg" alt="Stack Overflow SQL server before their upgrade in 2015" width="800" height="1067"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Go Distributed?
&lt;/h2&gt;

&lt;p&gt;We see there might be successful products and systems that run on a single machine or somewhere near that.&lt;/p&gt;

&lt;p&gt;But I'm not rejecting distributed systems completely here. So, why should we go distributed?&lt;/p&gt;

&lt;p&gt;In my opinion, the main reasons are:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;If you clearly see that you can't achieve the needed scalability on a single machine. To do that, you need to know &lt;strong&gt;"numbers"&lt;/strong&gt; – the requirements for expected load and system growth. And you also need to understand the limits of a single machine and of the software it runs. I'll go deeper into that in my next posts.&lt;/li&gt;
&lt;li&gt;If you see that you can use an &lt;strong&gt;existing self-contained and stable distributed system&lt;/strong&gt;, and you can build your system around it. A common example is databases. People who develop distributed databases have already solved many issues and addressed much of the complexity, and they usually hide some of this complexity inside. So, you, as a user, will only need a small portion of this complexity and delegate everything else to this central system. The problem here is that this "small portion of complexity" is usually still quite big, and people underestimate it.&lt;/li&gt;
&lt;li&gt;If you are doing an &lt;strong&gt;interview&lt;/strong&gt; for a big tech company 🙂&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  What's Next?
&lt;/h2&gt;

&lt;p&gt;Of course, this is not only about distributed vs. non-distributed. With this post, I'd like to start a series reviewing system design topics through the lens of lean system design.&lt;/p&gt;

&lt;p&gt;Next week, I'll pick a typical example of the system and walk through:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;how to estimate rough load without pretending you know the future;&lt;/li&gt;
&lt;li&gt;how to choose availability and consistency targets that match your business;&lt;/li&gt;
&lt;li&gt;and what "good enough" looks like for the first year.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Get the next one in your inbox
&lt;/h2&gt;

&lt;p&gt;I write Lean System Design — real benchmarks, real numbers, no Google-scale theater. New posts when I have something worth saying.&lt;/p&gt;

&lt;p&gt;Subscribe and I'll also send you the PostgreSQL Sizing Cheat Sheet: RPS, latency, and cost per 1k requests across every major RDS instance, broken down by workload type.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://saneengineer.com/postgres-cheat-sheet/?utm_source=devto&amp;amp;utm_medium=crosspost&amp;amp;utm_campaign=postgres-cheat-sheet" rel="noopener noreferrer"&gt;Get PostgreSQL Sizing Cheat Sheet here.&lt;/a&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>microservices</category>
      <category>programming</category>
      <category>systemdesign</category>
    </item>
  </channel>
</rss>
