<?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: Crack Tech</title>
    <description>The latest articles on DEV Community by Crack Tech (@cracktech).</description>
    <link>https://dev.to/cracktech</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%2F4194726%2Fd770c913-ac20-4f17-a249-37eac22a5a2a.png</url>
      <title>DEV Community: Crack Tech</title>
      <link>https://dev.to/cracktech</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/cracktech"/>
    <language>en</language>
    <item>
      <title>How I Attempt Any System Design Question (A Simple 4-Step Plan)</title>
      <dc:creator>Crack Tech</dc:creator>
      <pubDate>Mon, 26 Oct 2026 16:17:50 +0000</pubDate>
      <link>https://dev.to/cracktech/how-i-attempt-any-system-design-question-a-simple-4-step-plan-2235</link>
      <guid>https://dev.to/cracktech/how-i-attempt-any-system-design-question-a-simple-4-step-plan-2235</guid>
      <description>&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt; Don't start by drawing boxes. Go through the same 4 steps every time:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Requirements&lt;/strong&gt;: features, plus CLASS (Consistency, Latency, Availability, Scalability, Security)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Estimations&lt;/strong&gt;: users, storage and queries per second (divide by 10⁵ for "per day → per second")&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Detailed design&lt;/strong&gt;: APIs, data model and shard keys, then a 3-tier architecture you grow from&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Monitoring and alerting&lt;/strong&gt;: metrics, alerts, backups&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Below is each step with a worked example.&lt;/p&gt;




&lt;p&gt;The most common mistake I see in system design interviews happens in the first minute. The candidate hears the question, picks up the marker and starts drawing boxes.&lt;/p&gt;

&lt;p&gt;Ten minutes later there's a load balancer, three services and a cache on the board, and no clear idea of what is being built or for how many people.&lt;/p&gt;

&lt;p&gt;The fix is not learning more technologies. It's following the same plan every time. I'll go through the four steps using a small Twitter-like app as the example.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: Requirements
&lt;/h2&gt;

&lt;p&gt;Before drawing anything, agree on what you are building. There are two kinds of requirements.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Functional requirements&lt;/strong&gt; are the features. In a real company, a product manager usually gives you these. For Twitter:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create an account and log in&lt;/li&gt;
&lt;li&gt;Post a tweet&lt;/li&gt;
&lt;li&gt;Follow other users&lt;/li&gt;
&lt;li&gt;Like and comment on tweets&lt;/li&gt;
&lt;li&gt;See a feed of tweets from people you follow&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep the list short. Ask the interviewer which features matter most, and say out loud which ones you are leaving out.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-functional requirements&lt;/strong&gt; are how well the system must work. This part is the engineer's job, not the product manager's. I remember them as &lt;strong&gt;CLASS&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;C&lt;/strong&gt;onsistency: does everyone need to see the same data at the same moment? For a feed, eventual consistency is fine. A tweet showing up a few seconds late hurts nobody.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;L&lt;/strong&gt;atency: how fast must it respond? The feed should load quickly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A&lt;/strong&gt;vailability: how much downtime is acceptable? Five nines (99.999%) means only about 5 minutes of downtime in a whole year.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt;calability: how much traffic must it handle, and how will that grow?&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;S&lt;/strong&gt;ecurity: who can see and change what? This means proper authentication (you are who you say you are) and authorization (you are allowed to do this).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Don't just list these words. Say what each one means &lt;em&gt;for this system&lt;/em&gt;. "Eventual consistency is fine for the feed, so I'll choose availability" is an answer. "It should be consistent and available" is not.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Estimations
&lt;/h2&gt;

&lt;p&gt;Estimations tell you where the hard part of the design is. You don't need exact numbers, just the right size.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Assumptions first.&lt;/strong&gt; Write them down so the interviewer can follow your maths:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;500M total users, 200M daily active users (DAU)&lt;/li&gt;
&lt;li&gt;25% of DAU post one tweet a day, so 50M tweets a day&lt;/li&gt;
&lt;li&gt;Each user opens their feed 5 times a day&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Capacity planning (storage).&lt;/strong&gt; About how much data do we store?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A tweet with its likes and comments is roughly 2 KB&lt;/li&gt;
&lt;li&gt;50M tweets × 2 KB × 365 days ≈ 40 TB a year, before replication&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;QPS planning (queries per second).&lt;/strong&gt; One trick makes this easy: a day has 86,400 seconds, so round it to 100,000 (10⁵).&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Reads: 200M users × 5 feeds a day = 1,000M a day, and 1,000M / 10⁵ = &lt;strong&gt;10,000 reads per second&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Writes: 50M tweets a day, and 50M / 10⁵ = &lt;strong&gt;500 tweets per second&lt;/strong&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Bandwidth&lt;/strong&gt; is optional. Add it when the design moves large files, like videos or images.&lt;/p&gt;

&lt;p&gt;Now use the numbers. Reads are far higher than writes, so this is a &lt;strong&gt;read-heavy&lt;/strong&gt; system. That one fact drives the rest of the design: we will optimize for fast reads, even if writes get a little more expensive.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Detailed design
&lt;/h2&gt;

&lt;p&gt;This is the biggest step. I go through it in the same order every time.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;APIs.&lt;/strong&gt; List the main calls with their inputs and outputs:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;postTweet(authToken, content) → tweetId
followUser(authToken, userId) → success / failure
likeTweet(authToken, tweetId) → success / failure
getFeed(authToken) → list of tweets
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Data modelling.&lt;/strong&gt; Define the tables and, most importantly, the &lt;strong&gt;shard key&lt;/strong&gt; for each one. The shard key decides which machine a row lives on.&lt;/p&gt;

&lt;p&gt;For the Tweets table, there are two choices:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Shard by tweetId:&lt;/strong&gt; one user's tweets are spread across every machine. To get one user's tweets, you have to ask all of them and combine the results (scatter-gather). That is slow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Shard by userId:&lt;/strong&gt; all of one user's tweets are on one machine, so you go straight to it.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Shard by userId is better here. But say the trade-off: famous users with millions of followers make their machine very busy (a "hot" shard). You can handle that by adding more copies (replicas) of that shard.&lt;/p&gt;

&lt;p&gt;Pointing out a problem with your own choice is a good sign, not a weak one.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;High-level architecture.&lt;/strong&gt; I always start from the basic 3-tier architecture:&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%2Fublpdcm08pm7oek68u5j.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%2Fublpdcm08pm7oek68u5j.png" alt="3-tier architecture: clients, load balancer, web servers, load balancer, app servers, load balancer, DB servers" width="800" height="579"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;The starting point for almost every design: web servers, app servers and DB servers, with a load balancer in front of each tier.&lt;/em&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Tier 1, web servers:&lt;/strong&gt; the front door. They check who the user is (authentication) and call the right services to build a response (orchestration).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 2, app servers:&lt;/strong&gt; the business logic, split into services such as users, orders and payments.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Tier 3, DB servers:&lt;/strong&gt; the data, usually one database per service, each with replicas.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A load balancer sits in front of each tier, so you can add machines to any tier on its own when traffic grows.&lt;/p&gt;

&lt;p&gt;Then I grow it for the problem in front of me: a cache for the hot reads, queues for work that can happen later, and more services as the features need them. Then walk through one request from start to end. For example: "When I post a tweet, it goes into a queue. A worker finds my followers and adds the tweet to each of their feeds in the cache."&lt;/p&gt;

&lt;p&gt;Then cover the building blocks, but only where they matter for &lt;em&gt;this&lt;/em&gt; design:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Sharding:&lt;/strong&gt; what you split, and by which key&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Replication:&lt;/strong&gt; how many copies, and what happens when one fails&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Caching:&lt;/strong&gt; what you cache, and why (for example, each user's feed)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Authentication and authorization:&lt;/strong&gt; who can do what&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Anything specific to the problem:&lt;/strong&gt; for a calendar it's reminders, for payments it's never charging twice&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Step 4: Monitoring and alerting
&lt;/h2&gt;

&lt;p&gt;Most candidates run out of time before this step. Save five minutes for it, because it shows you think about running the system, not just building it.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Metrics to track:&lt;/strong&gt; latency of each API, success and failure rates, and resource usage (CPU, memory, disk)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Alerts:&lt;/strong&gt; notify the on-call engineer when a metric crosses a set threshold&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Backups:&lt;/strong&gt; for recovering lost data, and for offline reports and analytics&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  How I split a 45-minute interview
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Requirements: about 5 minutes&lt;/li&gt;
&lt;li&gt;Estimations: about 5 minutes&lt;/li&gt;
&lt;li&gt;Detailed design: about 25 to 30 minutes&lt;/li&gt;
&lt;li&gt;Monitoring and alerting: about 5 minutes&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The interviewer will interrupt and take you deeper into one area. That's good: it's where the real signal is. The plan keeps you from getting lost when you come back.&lt;/p&gt;
&lt;h2&gt;
  
  
  Mistakes I see most often
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Drawing boxes before agreeing on requirements&lt;/li&gt;
&lt;li&gt;Doing the estimations and then never using them&lt;/li&gt;
&lt;li&gt;Choosing a shard key without saying why&lt;/li&gt;
&lt;li&gt;Naming technologies ("use Kafka") without saying what problem they solve&lt;/li&gt;
&lt;li&gt;Skipping monitoring completely&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;You don't need to know every database to do well in a system design interview. You need a clear plan, and the habit of explaining &lt;em&gt;why&lt;/em&gt; at each step.&lt;/p&gt;

&lt;p&gt;Requirements, estimations, detailed design, monitoring. Practise them on a few problems and the order becomes automatic. Then you can spend your energy on the interesting parts.&lt;/p&gt;



&lt;p&gt;&lt;strong&gt;Over to you:&lt;/strong&gt; which step do you usually rush or skip in interviews? Tell me in the comments 👇&lt;/p&gt;

&lt;p&gt;&lt;em&gt;I write about system design and interview prep. If you're preparing for system design interviews, you can book a free 15-minute call:&lt;/em&gt;&lt;/p&gt;


&lt;div class="crayons-card c-embed text-styles text-styles--secondary"&gt;
    &lt;div class="c-embed__content"&gt;
      &lt;div class="c-embed__body flex items-center justify-between"&gt;
        &lt;a href="https://cracktech.app" rel="noopener noreferrer" class="c-link fw-bold flex items-center"&gt;
          &lt;span class="mr-2"&gt;cracktech.app&lt;/span&gt;
          

        &lt;/a&gt;
      &lt;/div&gt;
    &lt;/div&gt;
&lt;/div&gt;



</description>
      <category>systemdesign</category>
      <category>distributedsystems</category>
      <category>interview</category>
      <category>design</category>
    </item>
    <item>
      <title>"Design a Calendar System" Looks Easy. Here's Where Candidates Fail in the Interview</title>
      <dc:creator>Crack Tech</dc:creator>
      <pubDate>Wed, 21 Oct 2026 02:10:09 +0000</pubDate>
      <link>https://dev.to/cracktech/design-a-calendar-system-looks-easy-heres-where-candidates-fail-in-the-interview-li2</link>
      <guid>https://dev.to/cracktech/design-a-calendar-system-looks-easy-heres-where-candidates-fail-in-the-interview-li2</guid>
      <description>&lt;p&gt;"Design Calendar System" sounds simple. Create a meeting, invite people, show a grid of boxes.&lt;/p&gt;

&lt;p&gt;It isn't. Underneath sit some of the most interesting problems in system design: a read-heavy workload with a fan-out on every write, notifications that must reach every invitee, reminders that must fire at an exact minute for hundreds of millions of people, and recurring events that never really end.&lt;/p&gt;

&lt;p&gt;This walkthrough follows the structure we coach for a 45–60 minute interview: requirements, estimates, APIs, data model, high-level design, then the deep dives where the real signal is, and finally the AI follow-up more interviewers now ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Requirements
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Functional&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Create, read, update and delete meetings.&lt;/li&gt;
&lt;li&gt;Invite people by email, including people who don't use the product.&lt;/li&gt;
&lt;li&gt;Show a user's calendar for a day, week or month.&lt;/li&gt;
&lt;li&gt;Notify invitees when a meeting is created or changed.&lt;/li&gt;
&lt;li&gt;Remind participants a few minutes before a meeting (e.g. 15 minutes).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Nice to have: find a free slot across several people (free/busy), recurring meetings, time zones.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Non-functional&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Highly available: 99.99%. A calendar that's down means missed meetings.&lt;/li&gt;
&lt;li&gt;Low latency: calendar views in well under 500 ms (p99).&lt;/li&gt;
&lt;li&gt;Read-heavy: people look at their calendar far more often than they change it.&lt;/li&gt;
&lt;li&gt;Scalable: hundreds of millions of daily users.&lt;/li&gt;
&lt;li&gt;Consistency: eventual consistency is fine for invitees, but the organizer must see their own change immediately (read-your-writes).&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Interview tip: say why each requirement matters. "Eventually consistent, except read-your-writes for the organizer" shows judgement; "eventually consistent" alone is a buzzword.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  2. Back-of-the-envelope estimates
&lt;/h2&gt;

&lt;p&gt;Assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;2B users&lt;/li&gt;
&lt;li&gt;500M daily active users (DAU)&lt;/li&gt;
&lt;li&gt;20% of DAU create 2 meetings a day, and 30% create 1&lt;/li&gt;
&lt;li&gt;New meetings / day → 0.2 × 500M × 2 + 0.3 × 500M = 350M&lt;/li&gt;
&lt;li&gt;~4 participants per meeting → ~1.4B invites per day&lt;/li&gt;
&lt;li&gt;Calendar views / day → ~10 opens per DAU → 5B&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;QPS planning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Write QPS → 350M / 86,400 ≈ 3.5K/s average, ~10.5K/s peak&lt;/li&gt;
&lt;li&gt;Read QPS → 5B / 86,400 ≈ 50K QPS average, ~150K/s peak&lt;/li&gt;
&lt;li&gt;Read : write ratio ~15 : 1, so read-heavy&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Capacity planning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;1 KB meeting + ~100 Bytes per participant ≈ 1 KB + 4 × 100 Bytes = 1.4 KB&lt;/li&gt;
&lt;li&gt;1.4 KB × 350M ≈ 0.5 TB/day ≈ ~180 TB/year before replication (no media)&lt;/li&gt;
&lt;/ul&gt;

&lt;blockquote&gt;
&lt;p&gt;Interview tip: The numbers tell us where to spend effort: optimise reads, make writes reliable, and design the fan-out carefully.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  3. APIs
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;POST   /meetings                      create (title, start, duration, tz, invitees)
                                      + recurrence?, Idempotency-Key header
GET    /users/{id}/calendar?start&amp;amp;end  meeting summaries for a day/week/month (paginated)
GET    /meetings/{id}                 full details
PATCH  /meetings/{id}                 update only the changed fields (If-Match: version)
DELETE /meetings/{id}                 cancel
POST   /meetings/{id}/invitees        add invitees
DELETE /meetings/{id}/invitees/{uid}  remove an invitee
POST   /meetings/{id}/rsvp            accept / decline / maybe
GET    /free?users&amp;amp;start&amp;amp;end          free blocks only (for slot finding)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Two details interviewers notice:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The calendar view returns summaries, not just IDs. Returning IDs and then fetching details is an extra round trip on the hottest path.&lt;/li&gt;
&lt;li&gt;Updates carry a version (optimistic locking). Even if only the owner can edit, they can edit from two devices at once.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How an update works.&lt;/strong&gt; The client sends only the fields that changed, never the whole meeting row. Moving a meeting 30 minutes later 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;PATCH /meetings/m_123
If-Match: "7"
Content-Type: application/merge-patch+json
{ "start": "2026-10-20T10:30:00Z" }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Partial update.&lt;/strong&gt; Fields that aren't sent stay as they are, and null clears a field. The payload is tiny, and a client can't accidentally overwrite a field it never touched.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Version check.&lt;/strong&gt; If-Match: "7" means "apply this only if the meeting is still at version 7". The Meeting Service runs a conditional write: &lt;code&gt;UPDATE meetings SET start_utc = …, version = 8 WHERE meeting_id = 'm_123' AND version = 7&lt;/code&gt;. If another device changed the meeting first, nothing is updated and the API returns 412 Precondition Failed. The client refetches, shows the user the newer meeting, and lets them retry. The response to a successful update returns the whole updated meeting with its new version (ETag: "8").&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Invitees have their own endpoints.&lt;/strong&gt; Adding or removing people writes participant rows and sends notifications, so it isn't hidden inside a generic PATCH.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  4. Data model
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Users&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user_id (PK) → Shard Key&lt;/li&gt;
&lt;li&gt;email (unique)&lt;/li&gt;
&lt;li&gt;metadata&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Meetings&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;meeting_id (PK) → Shard Key&lt;/li&gt;
&lt;li&gt;owner_id&lt;/li&gt;
&lt;li&gt;title&lt;/li&gt;
&lt;li&gt;description&lt;/li&gt;
&lt;li&gt;start_utc&lt;/li&gt;
&lt;li&gt;duration&lt;/li&gt;
&lt;li&gt;version&lt;/li&gt;
&lt;li&gt;metadata&lt;/li&gt;
&lt;li&gt;list&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Participants&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;user_id → Shard Key&lt;/li&gt;
&lt;li&gt;meeting_id&lt;/li&gt;
&lt;li&gt;start_utc&lt;/li&gt;
&lt;li&gt;duration&lt;/li&gt;
&lt;li&gt;status (invited / accepted / declined)&lt;/li&gt;
&lt;li&gt;PK(user_id, start_utc, meeting_id)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Why two tables? The two hottest queries want different partitioning:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;"Show my week" → all of one user's meetings in a time range → partition by user_id, sort by time. One range scan on one shard. Once you get meeting_id, you can easily fetch meeting details based on meeting_id from meetings table.&lt;/li&gt;
&lt;li&gt;"Change this meeting" → one meeting and all its participants → partition by meeting_id.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The participants table denormalises the start time so the calendar view never has to join. The cost: moving a meeting rewrites one participant row per invitee. Writes are rare and reads are hot, so that's a good trade.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Interview tip: Tables in the same DB can have different shard keys.&lt;br&gt;
To fetch meeting details for a user, don't perform join between participants and meeting table, instead first fetch all the meeting Ids for the user within a day/week and then issue a separate query to DB to fetch meeting details. The Calendar Service does this server-side, so the client still gets summaries in one call.&lt;br&gt;
Optimization → Cache meeting details for the current and next week. Older meetings are rarely read, so caching them wastes memory.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  5. High-level design
&lt;/h2&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%2F8wg40jwxp1lwixebiwek.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%2F8wg40jwxp1lwixebiwek.png" alt=" " width="799" height="475"&gt;&lt;/a&gt;&lt;br&gt;
Async path for notification. Every change in the participants table is captured with change data capture (CDC) into an event queue. Downstream consumers react to it:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Event Subscriber Service subscribes to a change and put notifications in a queue.&lt;/li&gt;
&lt;li&gt;Change notifications (new invite, time changed, cancelled) are sent with immediately delivery to the delay queue. Delay queue with immediate delivery behaves as a FIFO queue.&lt;/li&gt;
&lt;li&gt;The Reminder Notifications are scheduled with delay delivery.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using CDC instead of having the Meeting Service publish events directly is deliberate. The database is the single source of truth, so an event can't be lost because a service crashed between "write the DB" and "publish the event".&lt;/p&gt;

&lt;p&gt;What if the Participant table can't be updated in the same transaction as meetings table.&lt;/p&gt;

&lt;p&gt;Use CDC to update participants table asynchronously.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Deep dive: keeping invitees up to date
&lt;/h2&gt;

&lt;p&gt;When a meeting changes, invitees should see it if online. Two options:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Pull (periodic refresh)&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Simple to build.&lt;/li&gt;
&lt;li&gt;Wasteful: most refreshes return nothing new, and at 500M DAU that's a lot of empty requests.&lt;/li&gt;
&lt;li&gt;Changes appear late.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Push&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Precise and cheap on the network.&lt;/li&gt;
&lt;li&gt;The server sends a tiny message, "meeting X changed", over Server-Sent Events or WebSocket to open web clients.&lt;/li&gt;
&lt;li&gt;The client then fetches only what changed.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Use push, and keep a light pull on app open as a safety net (pushes can be missed when a device is offline).&lt;/p&gt;

&lt;h2&gt;
  
  
  7. Deep dive: reminders 15 minutes before
&lt;/h2&gt;

&lt;p&gt;This is where strong candidates separate themselves. We need to fire hundreds of millions of reminders a day, at the right minute, exactly once, even when meetings move or get cancelled.&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%2Fsnu0ln21g8hclq9xl6m7.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%2Fsnu0ln21g8hclq9xl6m7.png" alt=" " width="799" height="556"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  8. Where agentic AI fits, and where it doesn't
&lt;/h2&gt;

&lt;p&gt;Interviewers now often add a follow-up: "How would you use AI here?" In agentic AI system design rounds it's sharper: "Which parts of this would you hand to an agent?" The strong answer starts by drawing a line.&lt;/p&gt;

&lt;p&gt;Keep the core deterministic. The Calendar DB, CDC, the event queue, fan-out and the delay queue must be exact, fast and cheap. An LLM call takes a second or more, costs real money per request, and can answer the same input differently twice. Nobody wants a reminder that fires "probably around 9:45", or a fan-out that decides which invitees deserve a notification. None of these components should be replaced by an agent.&lt;/p&gt;

&lt;p&gt;Put agents at the edges, where the input is human. The good fits are jobs that today need a person to read, judge or negotiate:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Finding a time: open everyone's calendar, compare, propose.
With Agent → "Find 30 minutes with Priya and Alex next week, mornings, not Friday" → it checks free, ranks slots and drafts the invite&lt;/li&gt;
&lt;li&gt;Rescheduling after a decline or a new conflict
With Agent → Proposes new times to everyone, collects the replies and books the slot that works.&lt;/li&gt;
&lt;li&gt;Empty meeting descriptions
With Agent → Drafts an agenda from the email thread or last meeting's notes.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  9. Common mistakes
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;One table for everything, so "show my week" becomes a scatter-gather across shards.&lt;/li&gt;
&lt;li&gt;Not creating Participants table and read fetch meetings created but not invited. Participants table is required and Invitees, organizer both should be added as participants.&lt;/li&gt;
&lt;li&gt;Relying on Redis key expiry for reminders.&lt;/li&gt;
&lt;li&gt;Doing the maths and not using it. Estimates should drive decisions (read-heavy → denormalize data).&lt;/li&gt;
&lt;li&gt;Putting an LLM in the core path, for example letting an agent decide who gets notified, or giving it direct database access.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;A great answer isn't the biggest diagram. It's a clear story: the numbers say it's read-heavy, so we shape the data for reads; writes fan out asynchronously through CDC; and reminders use a delay queue that survives retries and reschedules. AI belongs at the edges, where people talk to the system, not inside its core. Then you show you know where it breaks.&lt;/p&gt;

&lt;p&gt;Preparing for system design interviews, from classic designs like this to agentic AI systems? Crack Tech offers private 1:1 coaching and realistic mock interviews scored the way a hiring committee reads them. Book a free 15-minute call at cracktech.app.&lt;/p&gt;

</description>
      <category>systemdesign</category>
      <category>interview</category>
      <category>backend</category>
      <category>architecture</category>
    </item>
  </channel>
</rss>
