Posts

Showing posts from 2025

Balancing Speed vs Quality

  🧠 Mindset: The Engineering Tightrope Speed and quality are not strict opposites — they exist on a continuum . Too much focus on speed → you risk technical debt, instability, burnout . Too much focus on quality → you risk slow delivery, missed opportunities, analysis paralysis . A senior engineer’s or tech lead’s job is to continuously rebalance the two — not to “pick one.” “Move fast, but don’t break things that matter.” ⚡ Speed: MVP (Minimum Viable Product) and Early Validation Purpose: Validate assumptions fast. Get feedback loops early from real users. Reduce the risk of building the wrong thing. Practices: Lean MVPs: build the smallest version that proves a concept. Rapid prototyping: disposable code is okay if it accelerates learning. Iterative releases: short cycles, small scope, frequent deploys. Example: Build only the core feature → measure usage → iterate or discard. Use mock APIs or feature toggles to simulate d...

Understanding How async and await Work in .NET — Under the Hood

 Asynchronous programming in .NET has become almost second nature to developers — we sprinkle async and await everywhere to make our apps responsive. But what really happens when you mark a method as async and use await inside it? Let’s demystify how the compiler, runtime, and threads work together behind the scenes. ⚙️ The Promise of async and await At first glance, async and await seem magical. You write code like this: public async Task FetchDataAsync () { var data = await GetDataFromServerAsync(); Console.WriteLine(data); } It looks sequential — first we fetch data, then we print it — but it’s actually asynchronous and non-blocking . The question is: how does the compiler make that possible? 🧩 The Compiler Trick — State Machine Transformation When you mark a method with async , the C# compiler rewrites it into a state machine — a hidden class that controls what happens before and after each await . Think of each await as a “checkpoint.” When ...

Trie Data Structure: Introduction and Use Cases

Image
 When dealing with strings—like searching for words in a dictionary, building autocomplete systems, or implementing spell checkers—efficiency matters. One powerful tool for such tasks is the Trie (pronounced “try” ), also known as a prefix tree . In this post, we’ll explore what a Trie is, why it’s useful, how it works, and where you can apply it. What is a Trie? A Trie is a tree-like data structure designed for storing and retrieving strings efficiently. Unlike a binary search tree (BST), where nodes represent keys, each node in a Trie represents a single character of a string . For example, consider inserting the words: cat , car , apple and ant . The Trie would look like this: Notice how the common prefix "ca" is stored only once, making the Trie memory-efficient when handling large sets of overlapping words. Key Properties of a Trie Nodes represent characters : Each edge corresponds to a letter in a string. Root node is empty : It represents the starting poin...

Introduction to Bloom Filter

 A Bloom filter is a probabilistic data structure used to test whether an element is possibly in a set or definitely not in a set . It’s designed to be memory-efficient and very fast, but it allows false positives (saying an element might be in the set when it’s not) while guaranteeing no false negatives (if it says something is not in the set, it really isn’t). How it works: You start with a bit array (all bits set to 0). You have k different hash functions . To add an item: Compute its k hashes. Set the corresponding k positions in the bit array to 1. To check if an item is in the set: Compute its k hashes. If all those positions are 1 → item might be in the set (possible false positive). If any position is 0 → item is definitely not in the set . Example: Suppose you insert "cat" . Hash functions map "cat" to positions [3, 7, 12], so you set those bits. Later, you check "dog" . Its hashes are [3, 12...

Understanding the Hash Ring in Consistent Hashing

Image
 If you’ve ever looked into distributed systems or scalable caching, you’ve probably heard the term hash ring . It’s at the heart of consistent hashing — the algorithm that powers systems like DynamoDB, Cassandra, Riak, and distributed caches such as Memcached and Redis Cluster. In this post, we’ll break down what a hash ring is, how it works, and why it matters. What Is a Hash Ring? A hash ring is a conceptual circle that represents the entire range of hash values. Imagine the numbers from 0 to 2³² − 1 arranged in a circle. Nodes (servers) : Each server in your cluster is hashed to a point on the ring based on its identifier (e.g., IP address). Keys (data items) : Each key you want to store (e.g., cache key, user ID) is also hashed to a point on the ring. Assignment rule : A key is assigned to the first server found clockwise from its hash position. https://ably.com/blog/implementing-efficient-consistent-hashing Adding a Node When you add a new node: Hash the node’...

Best Practices for Access, ID, and Refresh Tokens

 When building modern applications with OAuth 2.0 and OpenID Connect, developers often get confused about where to store tokens . This decision is crucial because storing them incorrectly can open doors to serious vulnerabilities like XSS or CSRF attacks. Let’s break it down. Understanding the Tokens Access Token → Proves what you can do . It authorizes the client to call APIs on behalf of the user. ID Token → Proves who you are . It carries identity information (name, email, roles) about the authenticated user. Refresh Token (optional) → Used to obtain new access tokens without making the user log in again. Each token has a different lifespan and security sensitivity, so the storage strategy must match the risk. Storage on the User Side (Frontend) 1. Web Applications Best practice : Keep tokens in memory (JavaScript variables). Safer persistence : Use HTTP-only, Secure cookies if tokens must survive page reloads. Avoid : localStorage and sessionStorage for...

Understanding CQRS with Real-Life Examples

Image
  1. CQRS in an Online Store (Real-Life Example) In this diagram, we see an online store architecture applying CQRS: API Gateway : The entry point for all client requests. It routes incoming calls to the right backend service. Frontend Service : Connects to various backend services depending on the operation. Products Service (Write Side) : Responsible for updating product information (e.g., adding new products, changing prices, updating stock). Products Search Service (Read Side) : Maintains a denormalized, read-optimized view of product data so customers can quickly search and filter products. Reviews Service : Handles user reviews separately, but it also feeds into the search service so that reviews can be displayed alongside products. Notice that the Products Service and the Products Search Service do not share the same database. Instead, updates from the Products Service trigger events (via message queues or change notifications), and the Search Service...

Database Partitioning vs Sharding

Image
  🔹 What is Database Partitioning? Partitioning means splitting a large table into smaller pieces ( partitions ) to make queries faster and maintenance easier. Importantly, all partitions live inside the same database instance . Types of partitioning: Horizontal partitioning : Splits data by rows (e.g., orders by year). Vertical partitioning : Splits data by columns (e.g., frequently used vs. rarely used columns). ✅ Good for performance tuning when data still fits on one server. 🔹 Partitioning in Action (PostgreSQL Example) Imagine an orders table with millions of rows. We want to split it by year. Step 1: Create a partitioned table CREATE TABLE orders ( order_id BIGSERIAL PRIMARY KEY, customer_id INT NOT NULL , order_date DATE NOT NULL , amount NUMERIC ( 10 , 2 ) NOT NULL ) PARTITION BY RANGE (order_date); Step 2: Create partitions CREATE TABLE orders_2023 PARTITION OF orders FOR VALUES FROM ( '2023-01-01' ) TO ( ...

Global Server Load Balancing in the Azure Ecosystem

Image
  What is GSLB? Global Server Load Balancing (GSLB) is the practice of distributing user traffic across multiple regions or data centers. Unlike local load balancers that only manage traffic within a region, GSLB handles global routing, ensuring: Low latency – users are directed to the nearest endpoint. High availability – automatic failover if one region becomes unavailable. Disaster recovery – support for active-active or active-passive architectures. Geo-compliance – traffic can be routed based on geographic or regulatory requirements. GSLB in the Azure Ecosystem Azure provides multiple services to implement both regional load balancing and global server load balancing . Understanding their roles is key to designing a resilient and scalable cloud architecture. 1. Local Load Balancing (Regional) Azure Load Balancer (L4): Handles TCP/UDP traffic distribution within a region. Best for non-HTTP workloads such as gaming, VoIP, or real-time messaging. Azure Application Gateway ...

Understanding the OSI Model with a Real HTTP Request Example

Image
 Networking is everywhere — from browsing Google to streaming Netflix — but behind the scenes, a lot is happening to make sure data travels safely and reliably. To explain this, engineers often use the OSI Model (Open Systems Interconnection Model) : a framework that splits network communication into seven layers . In this post, we’ll break down the OSI layers, see what software or hardware handles them, and then walk through a real-life example of an HTTP request to Google . 🔹 The 7 Layers of the OSI Model Physical Layer → Transmits raw bits as electrical signals, radio waves, or light pulses. Devices: Cables, Wi-Fi, NICs, hubs. Data Link Layer → Moves frames between devices on the same network. Uses MAC addresses. Devices: Switches, NIC drivers. Network Layer → Routes packets between different networks. Uses IP addresses. Devices: Routers, firewalls. Transport Layer → Ensures reliable end-to-end delivery. Breaks data into segments. Handled...