<?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: Ayush Shrivastav</title>
    <description>The latest articles on DEV Community by Ayush Shrivastav (@ayushshrivastav).</description>
    <link>https://dev.to/ayushshrivastav</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F900851%2Fc3794f90-b512-4612-96cc-b4407b3be6e3.jpeg</url>
      <title>DEV Community: Ayush Shrivastav</title>
      <link>https://dev.to/ayushshrivastav</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ayushshrivastav"/>
    <language>en</language>
    <item>
      <title>Why Production Databases Break Normalization (And Why That's Okay)</title>
      <dc:creator>Ayush Shrivastav</dc:creator>
      <pubDate>Wed, 11 Mar 2026 18:36:31 +0000</pubDate>
      <link>https://dev.to/ayushshrivastav/why-production-databases-break-normalization-and-why-thats-okay-3hih</link>
      <guid>https://dev.to/ayushshrivastav/why-production-databases-break-normalization-and-why-thats-okay-3hih</guid>
      <description>&lt;p&gt;If you've taken any database course, you've been taught that normalization is the right way to design a schema. No duplicate data. Clean relationships. Every table with a single responsibility.&lt;/p&gt;

&lt;p&gt;Then you get a job at a real company, open the codebase, and see this:&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="n"&gt;messages&lt;/span&gt;
&lt;span class="c1"&gt;--------&lt;/span&gt;
&lt;span class="n"&gt;message_id&lt;/span&gt;
&lt;span class="n"&gt;channel_id&lt;/span&gt;
&lt;span class="n"&gt;user_id&lt;/span&gt;
&lt;span class="n"&gt;user_name&lt;/span&gt;
&lt;span class="n"&gt;user_avatar&lt;/span&gt;
&lt;span class="n"&gt;message_body&lt;/span&gt;
&lt;span class="n"&gt;created_at&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;user_name&lt;/code&gt;? &lt;code&gt;user_avatar&lt;/code&gt;? Right there in the messages table?&lt;/p&gt;

&lt;p&gt;Your first instinct might be to flag it as a bug. But here's the thing — this is not a mistake. Systems like this run at Slack, Discord, Instagram, and Twitter. These are deliberate decisions made by engineers who understand normalization perfectly. They just chose not to use it.&lt;/p&gt;

&lt;p&gt;This piece explains why.&lt;/p&gt;




&lt;h2&gt;
  
  
  First, what normalization actually solves
&lt;/h2&gt;

&lt;p&gt;Normalization isn't just an academic exercise. It solves a real problem: when the same information lives in more than one place, updates become dangerous.&lt;/p&gt;

&lt;p&gt;Say you store a user's name in the &lt;code&gt;users&lt;/code&gt; table and also inside each message they've sent. If the user changes their name, you now have to update two places. If one update fails halfway through, half your messages show the old name and half show the new one. That's a data consistency bug — and it's genuinely bad.&lt;/p&gt;

&lt;p&gt;A normalized schema avoids this entirely:&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="n"&gt;users&lt;/span&gt;          &lt;span class="n"&gt;messages&lt;/span&gt;
&lt;span class="c1"&gt;-----          --------&lt;/span&gt;
&lt;span class="n"&gt;id&lt;/span&gt;             &lt;span class="n"&gt;id&lt;/span&gt;
&lt;span class="n"&gt;name&lt;/span&gt;           &lt;span class="n"&gt;sender_id&lt;/span&gt; &lt;span class="err"&gt;→&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;avatar&lt;/span&gt;         &lt;span class="n"&gt;body&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now there's one source of truth. Loading a message with a username requires a JOIN:&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;body&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;avatar&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;
&lt;span class="k"&gt;JOIN&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt; &lt;span class="k"&gt;ON&lt;/span&gt; &lt;span class="n"&gt;u&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;sender_id&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;channel_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;m&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is correct, clean, and totally fine — until you're running it 300,000 times per second.&lt;/p&gt;




&lt;h2&gt;
  
  
  The actual bottleneck at scale
&lt;/h2&gt;

&lt;p&gt;Here's something most database courses don't tell you: production systems are not evenly split between reads and writes. Most systems are &lt;em&gt;overwhelmingly&lt;/em&gt; read-heavy.&lt;/p&gt;

&lt;p&gt;Twitter's public architecture data puts this into perspective. At 150 million active users, they were handling roughly 300,000 read requests per second for home timelines, versus about 6,000 write requests per second for new tweets. That's a 50-to-1 read/write ratio. For something like a message inbox or social feed, it can be even more extreme.&lt;/p&gt;

&lt;p&gt;When reads outnumber writes by that margin, every millisecond you can shave off a read multiplies across a huge volume. A JOIN that costs 10ms doesn't sound bad in isolation. But when you need to execute it 300,000 times a second across a distributed database cluster, that cost becomes the bottleneck.&lt;/p&gt;

&lt;p&gt;And JOINs are expensive in ways that aren't obvious. They require two table scans (or index lookups), loading data from potentially different disk pages, merging the results in memory, and sorting them. At modest table sizes this is fine. At hundreds of millions of rows spread across a sharded cluster, the database is doing significant work for every single request.&lt;/p&gt;




&lt;h2&gt;
  
  
  What denormalization actually is
&lt;/h2&gt;

&lt;p&gt;Denormalization is the decision to intentionally store the same data in more than one place to make reads faster.&lt;/p&gt;

&lt;p&gt;Going back to that messages table:&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="n"&gt;messages&lt;/span&gt;
&lt;span class="c1"&gt;--------&lt;/span&gt;
&lt;span class="n"&gt;message_id&lt;/span&gt;
&lt;span class="n"&gt;channel_id&lt;/span&gt;
&lt;span class="n"&gt;user_id&lt;/span&gt;
&lt;span class="n"&gt;user_name&lt;/span&gt;       &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="n"&gt;duplicated&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt;
&lt;span class="n"&gt;user_avatar&lt;/span&gt;     &lt;span class="err"&gt;←&lt;/span&gt; &lt;span class="n"&gt;duplicated&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;users&lt;/span&gt; &lt;span class="k"&gt;table&lt;/span&gt;
&lt;span class="n"&gt;message_body&lt;/span&gt;
&lt;span class="n"&gt;created_at&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now loading a channel's message history looks like this:&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;SELECT&lt;/span&gt; &lt;span class="n"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;user_avatar&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;message_body&lt;/span&gt;
&lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;messages&lt;/span&gt;
&lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;channel_id&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;42&lt;/span&gt;
&lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="n"&gt;created_at&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;
&lt;span class="k"&gt;LIMIT&lt;/span&gt; &lt;span class="mi"&gt;50&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;No join. One table. One index scan. The database does a fraction of the work.&lt;/p&gt;

&lt;p&gt;This is faster, cheaper in CPU and disk I/O, easier to cache, and simpler to scale horizontally — because no cross-table coordination is needed.&lt;/p&gt;




&lt;h2&gt;
  
  
  Discord: 4 trillion messages and zero joins
&lt;/h2&gt;

&lt;p&gt;Discord is probably the most documented example of this pattern at scale.&lt;/p&gt;

&lt;p&gt;When Discord launched in 2015, they stored messages in MongoDB. By late 2015, with 100 million messages in storage, queries were becoming slow and unpredictable as data grew beyond what fit in RAM. They migrated to Apache Cassandra, a database that forces you into denormalized design — there are no server-side JOINs in Cassandra at all.&lt;/p&gt;

&lt;p&gt;Their message schema looked something like this:&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;messages&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;channel_id&lt;/span&gt;  &lt;span class="nb"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;bucket&lt;/span&gt;      &lt;span class="nb"&gt;int&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;message_id&lt;/span&gt;  &lt;span class="nb"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;author_id&lt;/span&gt;   &lt;span class="nb"&gt;bigint&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="n"&gt;content&lt;/span&gt;     &lt;span class="nb"&gt;text&lt;/span&gt;&lt;span class="p"&gt;,&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;span class="n"&gt;channel_id&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;bucket&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;message_id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;WITH&lt;/span&gt; &lt;span class="n"&gt;CLUSTERING&lt;/span&gt; &lt;span class="k"&gt;ORDER&lt;/span&gt; &lt;span class="k"&gt;BY&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;message_id&lt;/span&gt; &lt;span class="k"&gt;DESC&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The key design decision is &lt;code&gt;(channel_id, bucket)&lt;/code&gt; as the composite partition key. All messages in a channel, within a ~10-day time window (the "bucket"), live on the same database node. A query for "last 50 messages in channel X" hits exactly one node, reads from one partition, and returns. No joins, no cross-node coordination.&lt;/p&gt;

&lt;p&gt;By 2022, Discord had grown to 177 Cassandra nodes handling trillions of messages. JVM garbage collection pauses were causing unpredictable latency spikes. They migrated to ScyllaDB (a C++ reimplementation of Cassandra with no JVM), dropping from 177 nodes to 72 while also cutting p99 insert latency from a variable 5–70ms range down to a steady 5ms.&lt;/p&gt;

&lt;p&gt;The schema design stayed fundamentally the same. Denormalized. Query-driven. No joins.&lt;/p&gt;




&lt;h2&gt;
  
  
  Twitter: precomputing your entire timeline
&lt;/h2&gt;

&lt;p&gt;Twitter's approach to denormalization is even more aggressive.&lt;/p&gt;

&lt;p&gt;In a normalized system, showing you your home timeline would work like this: query all users you follow, fetch their recent tweets, merge and sort by time. At scale, this is a scatter-gather operation — hitting potentially thousands of small queries per timeline load. Completely impractical.&lt;/p&gt;

&lt;p&gt;What Twitter does instead is called fan-out on write. When you post a tweet, a background process immediately pushes your tweet ID into the Redis timeline cache of every one of your followers. If you have 20,000 followers, that's 20,000 cache writes triggered by your single post.&lt;/p&gt;

&lt;p&gt;The read path becomes trivially simple. When you open your timeline, Twitter reads your pre-built list from Redis. Your 800-tweet timeline is already there, pre-sorted, waiting. The read takes about 5 milliseconds.&lt;/p&gt;

&lt;p&gt;This is denormalization taken to its logical extreme. The tweet ID is physically duplicated across N followers' data stores — not in the database sense, but in the cache sense. Write time is more expensive. Read time is nearly free.&lt;/p&gt;

&lt;p&gt;One obvious problem: Lady Gaga had 31 million followers at one point. A single tweet from her would require 31 million cache writes. Twitter handles this with a hybrid approach — for accounts above a certain follower threshold, they skip the fan-out and instead merge the celebrity's tweets at read time. Most users get the precomputed timeline. Celebrities are handled as a special case.&lt;/p&gt;




&lt;h2&gt;
  
  
  Instagram's like count problem
&lt;/h2&gt;

&lt;p&gt;Instagram ran into a specific version of this problem around engagement metrics.&lt;/p&gt;

&lt;p&gt;In a normalized schema, counting likes looks like this:&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;SELECT&lt;/span&gt; &lt;span class="k"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;FROM&lt;/span&gt; &lt;span class="n"&gt;likes&lt;/span&gt; &lt;span class="k"&gt;WHERE&lt;/span&gt; &lt;span class="n"&gt;post_id&lt;/span&gt; &lt;span class="o"&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;On a busy post, the &lt;code&gt;likes&lt;/code&gt; table has millions of rows. Even with an index, counting them is work the database has to do on every request — and Instagram serves hundreds of millions of users who are all loading posts and seeing like counts constantly.&lt;/p&gt;

&lt;p&gt;When a celebrity posted something, the spike in traffic would hammer this query on every load. The database struggled.&lt;/p&gt;

&lt;p&gt;The fix was straightforward: add a &lt;code&gt;like_count&lt;/code&gt; column directly to the &lt;code&gt;posts&lt;/code&gt; table. When someone likes a post, you write to &lt;code&gt;likes&lt;/code&gt; and you also increment &lt;code&gt;like_count&lt;/code&gt; in &lt;code&gt;posts&lt;/code&gt;. Now the read path for a like count is a single indexed lookup returning a single value.&lt;/p&gt;

&lt;p&gt;The tradeoff: writes are slightly more complex, and the &lt;code&gt;like_count&lt;/code&gt; column is technically derived data (it duplicates what you could compute from the &lt;code&gt;likes&lt;/code&gt; table). But the query went from being expensive to being instant. That's a tradeoff Instagram very deliberately made.&lt;/p&gt;




&lt;h2&gt;
  
  
  Microservices make denormalization unavoidable
&lt;/h2&gt;

&lt;p&gt;There's another context where denormalization isn't really optional: distributed microservice architectures.&lt;/p&gt;

&lt;p&gt;If your user data lives in a User Service and your message data lives in a Message Service, there is no JOIN. You can't run a SQL query that spans two independently deployed, separately scaled services with separate databases.&lt;/p&gt;

&lt;p&gt;You have a few options:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Load the message, then make an HTTP call to the User Service to get the username. This adds a network round-trip to every message load — not great when loading 50 messages at once.&lt;/li&gt;
&lt;li&gt;Batch the calls. Slightly better but still adds latency and coupling.&lt;/li&gt;
&lt;li&gt;Store the username inside the message when it's created. No cross-service call needed at read time.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Option 3 is denormalization, and it's the most common approach in real microservice architectures. The Message Service stores enough user data to render messages without calling anyone else. When a user changes their name, the message records don't immediately reflect it — but that's an acceptable tradeoff for most systems. Yesterday's chat messages showing your old username for a few seconds is not a critical business failure.&lt;/p&gt;




&lt;h2&gt;
  
  
  The real cost of denormalization
&lt;/h2&gt;

&lt;p&gt;Denormalization is not free. The engineering tradeoff is real, and it's worth being honest about it.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Update complexity.&lt;/strong&gt; If a user changes their avatar, and their avatar URL is embedded in thousands of message records, you now have to update all of those records. In some systems this is acceptable (the old avatar is just stale, not wrong). In others you need a propagation mechanism — typically an event stream that broadcasts the change and downstream services update their own copies.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Eventual consistency.&lt;/strong&gt; In distributed systems, that propagation doesn't happen instantly. There's a window where your data is inconsistent — the users table has the new name, but message records still show the old one. Systems that use this pattern explicitly accept eventual consistency as a design choice.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Storage cost.&lt;/strong&gt; Storing the same data multiple times costs more. At small scale this barely matters. At Discord's scale (petabytes of messages), duplicating even a small amount of data per message adds up.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Schema evolution.&lt;/strong&gt; If a denormalized field changes meaning or format, you have to update it everywhere it's been copied — which might mean migrating billions of rows.&lt;/p&gt;




&lt;h2&gt;
  
  
  How production systems handle both
&lt;/h2&gt;

&lt;p&gt;Most well-designed systems don't pick one approach and abandon the other. They use normalization where correctness matters most and denormalization where read performance matters most.&lt;/p&gt;

&lt;p&gt;A common architecture:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Normalized database (source of truth)
           ↓
     Event stream (Kafka)
           ↓
  Denormalized read tables
           ↓
       API queries
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The normalized database is where you write to. It's correct, consistent, and acts as the ground truth for your data. When something changes here, an event gets published.&lt;/p&gt;

&lt;p&gt;Downstream services consume those events and update their own denormalized projections — tables or caches optimized for specific read patterns. These projections might live in Redis, Cassandra, Elasticsearch, or a separate PostgreSQL schema. They're not the source of truth, but they're what your APIs query because they're fast.&lt;/p&gt;

&lt;p&gt;This pattern has a name — CQRS (Command Query Responsibility Segregation) — and it's what Netflix, LinkedIn, Uber, and most large-scale platforms use in one form or another. Netflix processes 140 million hours of viewing data per day through Kafka, with multiple downstream consumers each building their own optimized projection for recommendations, billing, and analytics.&lt;/p&gt;




&lt;h2&gt;
  
  
  The insight worth taking away
&lt;/h2&gt;

&lt;p&gt;Database theory teaches you how to design schemas that are correct. Production engineering teaches you how to design schemas that are fast under real load.&lt;/p&gt;

&lt;p&gt;Normalization is right in the sense that it prevents a class of consistency bugs. It belongs in your schema wherever data correctness is non-negotiable.&lt;/p&gt;

&lt;p&gt;Denormalization is right in the sense that JOINs at scale are expensive, network round-trips add up, and precomputed data is faster than computed data. It belongs in your read paths, your caches, and your projections.&lt;/p&gt;

&lt;p&gt;The engineers at Discord, Twitter, Instagram, and Netflix aren't ignoring normalization. They understand it well enough to know when breaking it is the right call.&lt;/p&gt;

&lt;p&gt;That's the difference between knowing the rules and knowing when to apply them.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Real-world data referenced in this post comes from Discord's engineering blog (message storage architecture), Twitter's 2012 architecture documentation, Instagram's engineering posts on sharding and denormalization, and Netflix's TechBlog on viewing data storage.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>database</category>
      <category>sql</category>
      <category>systemdesign</category>
    </item>
    <item>
      <title>Sonar Cude Basic Understanding</title>
      <dc:creator>Ayush Shrivastav</dc:creator>
      <pubDate>Tue, 25 Apr 2023 07:01:54 +0000</pubDate>
      <link>https://dev.to/ayushshrivastav/sonar-cude-basic-understanding-3pgl</link>
      <guid>https://dev.to/ayushshrivastav/sonar-cude-basic-understanding-3pgl</guid>
      <description>&lt;h2&gt;
  
  
  Advantages of SonarQube
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;SonarQube detects bugs in the code automatically and gives alerts to the developers to resolve the issues before rolling it out for production.&lt;/li&gt;
&lt;li&gt;It aids developers in reducing code redundancy and complexity&lt;/li&gt;
&lt;li&gt;Maintenance time and cost of production and make code easy to read and understand.&lt;/li&gt;
&lt;li&gt;Developers receive regular feedback on coding standards and quality issues which helps in increasing the programming skills.&lt;/li&gt;
&lt;li&gt;It is scalable.&lt;/li&gt;
&lt;li&gt;It enables continuous code quality management and decreases the cost and risk associated with software management.&lt;/li&gt;
&lt;li&gt;SonarQube provides additional value and professional support. Services including development, technical support, consulting and training are designed to help companies get long term benefits.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Disadvantages of SonarQube
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Learning curve is hard&lt;/li&gt;
&lt;li&gt;Report generation is often very time consuming&lt;/li&gt;
&lt;li&gt;Initial setup is quite complicated&lt;/li&gt;
&lt;li&gt;Sometimes it reports an issue that is not actually a problem, or false negatives.&lt;/li&gt;
&lt;li&gt;Plugins for some languages are available only in commercial versions of the platform.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Evidence of Stability
&lt;/h2&gt;

&lt;p&gt;SonarQube is known for its stability, partly because they do not release updates too frequently. For instance, their product SonarQube Scanner has only undergone three major releases over the past six to seven years.&lt;br&gt;
&lt;a href="https://www.npmjs.com/package/sonarqube-scanner?activeTab=versions"&gt;sonarqube-scanner npm&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Competitors of SonarQube
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Embold&lt;/li&gt;
&lt;li&gt;Checkmarx SAST&lt;/li&gt;
&lt;li&gt;Synopsys Coverity&lt;/li&gt;
&lt;li&gt;Micro Focus Fortify Static Code Analyzer (SCA) &lt;/li&gt;
&lt;li&gt;Veracode Static Analysis&lt;/li&gt;
&lt;li&gt;Snyk Code&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the following are some well-known static code analysis tools, it is possible that there are numerous others available as well.&lt;/p&gt;

&lt;h2&gt;
  
  
  What is best time of add SonarCube ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;The best time to add SonarQube to your project is as early as possible in the development process. This allows you to continually analyze and improve the quality of your code throughout the project's lifecycle. By identifying and addressing potential issues early on, you can reduce the risk of errors and technical debt down the line. Integrating SonarQube into your project from the beginning can help ensure that you are delivering a high-quality product.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  If we add SonarCube after some development of project then what is strategies of  refactoring old code ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One strategy for refactoring old code is to focus on the critical issues identified by SonarQube first, such as security vulnerabilities or major code smells. Once these issues have been addressed, you can move on to tackling less critical issues.&lt;/li&gt;
&lt;li&gt;Another strategy is to prioritize refactoring code that is frequently modified or has a high level of complexity. This can help reduce technical debt and make the codebase more maintainable in the long run.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It's important to keep in mind that refactoring should be done incrementally and carefully to avoid introducing new issues or disrupting the functionality of the code. With SonarQube's guidance and the help of experienced developers, you can gradually improve the quality of your codebase and ensure that it meets high standards of maintainability and reliability.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to reduce the technical debt in Sonarqube?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Prioritize issues:&lt;/strong&gt; Focus on addressing critical issues first, such as security vulnerabilities or major code smells. These issues can have a significant impact on the quality of your codebase and should be tackled as soon as possible.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Address code duplication:&lt;/strong&gt; Code duplication can increase technical debt and make your codebase more difficult to maintain. Use SonarQube's code duplication detection to identify areas where code can be consolidated or refactored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Improve code coverage:&lt;/strong&gt; Low code coverage can indicate that important parts of your codebase are not being tested. Use SonarQube's test coverage analysis to identify areas where additional tests are needed and ensure that your codebase is adequately covered.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Monitor code complexity:&lt;/strong&gt; High code complexity can make your codebase difficult to understand and maintain. Use SonarQube's code complexity analysis to identify areas where code can be simplified or refactored.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Set coding standards:&lt;/strong&gt; Define coding standards for your project and use SonarQube to enforce them. This can help ensure that your codebase is consistent and maintainable.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  List out all risk to our project because of SonarCube ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Integration complexity:&lt;/strong&gt; Integrating SonarQube into your development workflow can be complex, especially if you have a large or complex codebase. There may be some initial setup and configuration required, which can be time-consuming.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;False positives:&lt;/strong&gt; SonarQube's analysis is based on a set of rules and algorithms that may not always accurately reflect the specific needs of your project. This can result in false positives, where issues are flagged that are not actually problems.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance impact:&lt;/strong&gt; Running code analysis with SonarQube can take time and resources, especially on larger codebases. This can impact the performance of your development environment and slow down your development process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintenance overhead:&lt;/strong&gt; SonarQube requires ongoing maintenance and configuration to ensure that it continues to provide accurate results. This can add an additional overhead to your development process.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Increase in development time:&lt;/strong&gt; While resolving issues during development will definitely increase the development time.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  How to overcome risk?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;To reduce false positives, customize SonarQube's rule sets to fit your project's specific needs. You can also create your own custom rules and modify existing rules to better suit your project.&lt;/li&gt;
&lt;li&gt;To minimize the performance impact of running code analysis with SonarQube, use a dedicated server for analysis, optimize SonarQube's configuration for your specific environment, and consider running analysis during off-hours.&lt;/li&gt;
&lt;li&gt;Use SonarLint, a SonarQube plugin, to perform real-time code analysis directly in your integrated development environment (IDE). This will allow you to address issues as you write code, reducing the time required to fix issues later on.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What benefits we will get ?
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Improved code quality.&lt;/li&gt;
&lt;li&gt;Increased productivity by decrease the time of manual code review.&lt;/li&gt;
&lt;li&gt;Consistent coding standards.&lt;/li&gt;
&lt;li&gt;Improve in developer coding skills and practices.&lt;/li&gt;
&lt;/ul&gt;

</description>
    </item>
    <item>
      <title>Complete Roadmap to Learn React</title>
      <dc:creator>Ayush Shrivastav</dc:creator>
      <pubDate>Sun, 31 Jul 2022 10:41:00 +0000</pubDate>
      <link>https://dev.to/ayushshrivastav/complete-roadmap-to-learn-react-3n71</link>
      <guid>https://dev.to/ayushshrivastav/complete-roadmap-to-learn-react-3n71</guid>
      <description>&lt;p&gt;If you are new to React JS then you would have faced a problem that what to learn in react and what not to, what is more important and on which concept I need to focus more all these question pops up in mind every time we start learning new things.&lt;/p&gt;

&lt;p&gt;In this blog we will be discussing a complete roadmap to learn react, On which part you have to focus more and a task at the end  based on complete react concept. &lt;/p&gt;

&lt;p&gt;If you will follow this roadmap then at the end you can say yourself that you know react Js in any of the interviews.&lt;/p&gt;

&lt;p&gt;Lets not waste our time and start with first Prerequisites for Learning react.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prerequisites for Learning React&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Html (basic)&lt;/li&gt;
&lt;li&gt;CSS (basic)&lt;/li&gt;
&lt;li&gt;JavaScript (intermediate)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Ya that's all you want to know before learning React.&lt;/p&gt;

&lt;p&gt;If you know the Prerequisites then we are good to Go for learning React JS. Lets first see the Overview of and then we will discuss each one in detail.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Topics To learn in React&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Basic React Concepts&lt;/li&gt;
&lt;li&gt;Advance React Concepts&lt;/li&gt;
&lt;li&gt;Hooks&lt;/li&gt;
&lt;li&gt;React-Router&lt;/li&gt;
&lt;li&gt;Store Management (Redux)&lt;/li&gt;
&lt;li&gt;Api calls in React (Axios)&lt;/li&gt;
&lt;li&gt;A task on Complete React Concept&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Now lets discuss each Topics in details and how and where can you learn these concepts ,lets discuss everything.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;1. Basic React Concepts&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;So in Basics react concepts we have to just focus on the following things.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is JSX ?&lt;/li&gt;
&lt;li&gt;How an Element is Rendered?&lt;/li&gt;
&lt;li&gt;What is components? (functional and class component)&lt;/li&gt;
&lt;li&gt;What is state and why they are required?&lt;/li&gt;
&lt;li&gt;What is props?&lt;/li&gt;
&lt;li&gt;How can we pass props from parent to child component?&lt;/li&gt;
&lt;li&gt;Conditional Rendering&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Focus on these concepts more because these will be the base of your react building structure. &lt;/p&gt;

&lt;p&gt;After learning these concepts lets move towards our Advance Concepts of React&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;2. Advance React Concepts&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;How to Print list with the help of Map method in JSX and importance of key in list?&lt;/li&gt;
&lt;li&gt;Handling Forms in React&lt;/li&gt;
&lt;li&gt;How to pass data from child component to parent component?(Lifting State Up)&lt;/li&gt;
&lt;li&gt;How to use Reference(ref) in React?&lt;/li&gt;
&lt;li&gt;Fragments&lt;/li&gt;
&lt;li&gt;Component Lifecycle methods&lt;/li&gt;
&lt;li&gt;Higher order component.&lt;/li&gt;
&lt;li&gt;Context&lt;/li&gt;
&lt;li&gt;difference between Controlled and uncontrolled form&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Congrats Now you know the React JS and their functionality .&lt;br&gt;
Its time to strong your Concepts and learn about hooks in react.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;3. Hooks&lt;/strong&gt;&lt;br&gt;
Moving forward hooks is the one of the most important concepts of react. Lets take a look at it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is hooks?&lt;/li&gt;
&lt;li&gt;Some important hooks like useState, useEffect and useMemo.&lt;/li&gt;
&lt;li&gt;Some important rules of hooks.&lt;/li&gt;
&lt;li&gt;how to make a custom hook.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;4. React Router&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Routing?&lt;/li&gt;
&lt;li&gt;How Routing is Done in React?&lt;/li&gt;
&lt;li&gt;Difference between Link and Navlink.&lt;/li&gt;
&lt;li&gt;UseNavigate, UseParams , UseSearchParams hooks.&lt;/li&gt;
&lt;li&gt;Nested Routing.&lt;/li&gt;
&lt;li&gt;Parameterise Routing.&lt;/li&gt;
&lt;li&gt;Conditional Routing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;5. Store Management (Redux)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Why centralized State (store) is required?&lt;/li&gt;
&lt;li&gt;Basic informations about redux and redux toolkit&lt;/li&gt;
&lt;li&gt;What is Reducer in Redux?&lt;/li&gt;
&lt;li&gt;what are Actions and Action Type?&lt;/li&gt;
&lt;li&gt;How to get the store through useSelector hook?&lt;/li&gt;
&lt;li&gt;How to dispatch an action?&lt;/li&gt;
&lt;li&gt;Any middleware for redux and why middleware is required (Thunk or Saga)?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;6. Api calls in React (Axios)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What is Api and how we can fire a request through fetch?&lt;/li&gt;
&lt;li&gt;How Axios is better than fetch?&lt;/li&gt;
&lt;li&gt;How can we fire Get,Post,Put and Delete request through Axios?&lt;/li&gt;
&lt;li&gt;What is Axios Interceptor and Why it is required?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Task&lt;/strong&gt;&lt;br&gt;
Follow each step and move to next step after developing and verifying First one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;- Step 1&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;create a react app using create react app CLI command&lt;/li&gt;
&lt;li&gt;Make 3 screens (login page , Dashboard , Users)&lt;/li&gt;
&lt;li&gt;Login Page should not have any navbar&lt;/li&gt;
&lt;li&gt;Rest all pages will have same navbar and user information will be their at on any corner of navbar&lt;/li&gt;
&lt;li&gt;You can choose your style of UI and be creative with it.&lt;/li&gt;
&lt;li&gt;Add Routing to your App.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;- Step 2&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Make a Json Web server for fake Data to use as Api.&lt;/li&gt;
&lt;li&gt;Fill up Json server with some demo data of users.
{
 user_name:"Ayush Shrivastav",
 user_email:"&lt;a href="mailto:ayushshrivastava076@gmail.com"&gt;ayushshrivastava076@gmail.com&lt;/a&gt;"
 password:"789365ayush"
 Role:"admin"/"user"
 Designation:"CEO"
}&lt;/li&gt;
&lt;li&gt;Now use these data for the user login with the help of api call.&lt;/li&gt;
&lt;li&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>learnreact</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
