Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
15 posts found #system-design
System Design Case Study: Flash Sales and Ticketing
Software Architecture PART 15

System Design Case Study: Flash Sales and Ticketing

What prevents overselling in a flash sale is doing the stock check and the decrement in a single atomic step; a waiting room served from a CDN absorbs the spike, holds with a TTL manage the payment window, and expired holds return stock in the same statement. Real output with 2,000 concurrent buyers for 100 tickets: 2,000 reservations from naive code, a conditional UPDATE and optimistic concurrency, plus payment timeouts and bot defense.

8 Nov 2026 13 min 5
System Design Case Study: Chat and Notification System
Software Architecture PART 14

System Design Case Study: Chat and Notification System

In a chat system, connections live on stateful gateways while order and storage live in a stateless chat service: a message is stored first, gets a sequence number from a per-conversation server counter, the recipient's gateway is found through presence, and offline recipients get a push. Real output for routing between two gateways with Redis and for ordering, deduplication and gap detection by seq on the client, read receipts, group fan-out and message storage.

8 Nov 2026 11 min 4
System Design Case Study: News Feed and Timeline
Software Architecture PART 13

System Design Case Study: News Feed and Timeline

Fan-out on write is the default for a news feed, but because followers follow a power law, a single celebrity post turns into a million writes; the fix is a hybrid model that merges accounts above a high threshold at read time, a feed cache holding only post IDs, and cursor pagination. A computed capacity table, a push, pull and hybrid simulation, and real output comparing offset and cursor on a Redis sorted set.

8 Nov 2026 11 min 4
System Design Case Study: Designing a URL Shortener
Software Architecture PART 12

System Design Case Study: Designing a URL Shortener

A URL shortener is a read-heavy system: ~3,900 redirects against ~40 writes per second, so it needs a stateless redirect path, cache-aside, codes that never collide and are hard to guess, and 302 rather than 301 for analytics. A computed capacity table, a real measurement of hash collisions, counter + bijective mapping + base62, 301/302 curl output, aliases, expiration and abuse.

8 Nov 2026 12 min 4
Generating Unique IDs: Auto-Increment, UUIDv4, UUIDv7 and Snowflake
Software Architecture PART 11

Generating Unique IDs: Auto-Increment, UUIDv4, UUIDv7 and Snowflake

In a sharded or multi-instance system, choosing an ID is a trade-off between uniqueness, sortability, size, coordination and what the ID leaks: UUIDv7 needs no coordination and is index friendly, Snowflake fits in 64 bits but needs worker ID and clock management. Real output showing .NET's CreateVersion7 doesn't guarantee order within a millisecond, a C# Snowflake generator and JavaScript's 2^53 limit.

8 Nov 2026 11 min 4
Reliability Patterns: Timeouts, Retries, Backoff with Jitter, Circuit Breakers and Load Shedding
Software Architecture PART 10

Reliability Patterns: Timeouts, Retries, Backoff with Jitter, Circuit Breakers and Load Shedding

Against a slow or failed dependency you need, in order, a timeout chosen from p99.9, jittered retries at a single layer and only for idempotent operations, a retry budget, a circuit breaker and bulkhead per dependency, and finally load shedding and graceful degradation. Real simulation output for retry amplification (27 and 243 calls), jitter, a 10% retry budget and a circuit breaker, failover, and .NET's standard resilience handler defaults.

8 Nov 2026 12 min 5
Designing Rate Limiting: Token Bucket, Sliding Window and a Distributed Rate Limiter
Software Architecture PART 09

Designing Rate Limiting: Token Bucket, Sliding Window and a Distributed Rate Limiter

A single rate limit needs its counter in a single place: ASP.NET Core's built-in limiter keeps counters in each instance's memory, so three instances triple the limit; the fix is an atomic counter in the gateway or in Redis. A comparison of five algorithms, a distributed sliding window limiter with Redis and Lua with real output, 429, Retry-After, the IETF RateLimit header draft and the DoS risk of partition keys.

8 Nov 2026 13 min 4
Asynchronous Processing: Queues, Workers, Fan-Out and Backpressure
Software Architecture PART 08

Asynchronous Processing: Queues, Workers, Fan-Out and Backpressure

Heavy work that is not part of the response moves out of the request to a queue and workers; the API returns 202 Accepted and a status address. In a real experiment the synchronous invoice endpoint times out 52 of 100 concurrent requests yet still renders 100 PDFs, while the bounded-queue version answers in 9 ms and pushes back with 503 and Retry-After when full; asynchrony decouples the work's timing, it doesn't speed it up.

8 Nov 2026 10 min 4
Consistent Hashing: Hash Rings, Virtual Nodes and a C# Implementation
Software Architecture PART 07

Consistent Hashing: Hash Rings, Virtual Nodes and a C# Implementation

Consistent hashing is a distribution method that moves only about 1/(N+1) of the keys when the node count changes: going from 4 to 5 nodes hash % N moves 80% of the keys, while a hash ring written in C# with 200 virtual nodes moves ~20% and keeps the load within ±10% of the average. The properties are pinned down with xUnit tests; rendezvous hashing, Redis Cluster's hash slots and the string.GetHashCode trap are covered too.

8 Nov 2026 9 min 4
Scaling the Data Layer: Replication, Sharding and SQL vs NoSQL
Software Architecture PART 06

Scaling the Data Layer: Replication, Sharding and SQL vs NoSQL

Scaling the data layer starts with access patterns: replication scales reads and availability but not writes, and sharding scales writes but turns queries without the shard key into scatter-gather. In a million-order experiment the customer query returns from one shard in 0.1 ms while the last-30-days query scans all four shards end to end; an async replica doesn't show a new order and needs a read-your-writes fix, and going from 4 to 5 shards with hash % N moves 80% of customers.

8 Nov 2026 11 min 4
Caching Strategies: Cache-Aside, Write-Through, Write-Behind and Cache Stampede
Software Architecture PART 05

Caching Strategies: Cache-Aside, Write-Through, Write-Behind and Cache Stampede

Cache-aside is the most common strategy, but the moment a popular entry expires all its load hits the database: in a real Redis experiment 200 concurrent requests produce 200 queries, and request coalescing brings that down to 1. 10,000 entries warmed in bulk expire in the same second without jitter, while ±10% jitter cuts the busiest second to 109 entries; early refresh with XFetch turns 500 recomputations into 1, and hot keys are found with Redis' LFU counter.

8 Nov 2026 11 min 5
Load Balancing: L4 vs L7, Algorithms, Health Checks and Sticky Sessions
Software Architecture PART 04

Load Balancing: L4 vs L7, Algorithms, Health Checks and Sticky Sessions

A load balancer's algorithm decides the latency users see when one instance slows down: in a real YARP experiment round robin pushes p99 to 4.6 seconds, while LeastRequests and power of two choices cut traffic to the slow instance by themselves and keep p99 at 300 ms. Only a health check removes a crashed instance (133 errors down to 35); the post also covers L4 vs L7, the cost of sticky sessions, connection draining and global load balancing with GeoDNS and anycast.

8 Nov 2026 11 min 4
Blog Map