Co-Founder @ Coder Army | Senior Software Engineer | Travel Enthusiast

Delhi, India
So it’s possible to get scared of your own creation that it might outsmart you someday and will take over the world.
5
23
668
I’m scared of AI. 🥸
3
20
889
Aditya Tandon retweeted
Mahool Bana diya hai aapne achee se....
11
12
181
6,170
Every new AI update feels less and less important. The initial shock value of AI has worn off, moving the industry from revolutionary breakthroughs to incremental engineering tweaks.
2
30
1,240
I’ve completed THE most in-depth Java & Spring Boot series on YouTube. Even better than many paid course. (See yourself to believe. Channel : Coder Army) If your attention span can survive hour long lectures, trust me you’ll come out the other side as a completely different engineer.
5
16
272
10,452
7 years since I graduated, and today I walked back into my BTech college. I thought I had left those days behind, but all it took was stepping through the gate for years of memories to come flooding back like they had been waiting there all along.
2
38
1,744
Forward Deployed Engineer. Free. 🔥
FORWARD Deployed Engineer..... @adityatandon02 guruji announcement on 15 august.....
3
2
28
2,115
90% of LLD interview solutions are terrible production code. They’re optimized to impress interviewers, not engineers. Factory Strategy Observer Decorator All inside a Parking Lot application with 200 lines of code. If your solution needs four design patterns to park a car then maybe the parking lot isn’t the problem.
1
23
1,530
Aditya Tandon retweeted
Finally My First video which has crossed the mark of 1 Million views. Till now we have created more than 350+ long form videos on Coder army but this was the first video of the channel and it got lot of love from the community... Hello Coder Army kaise hai aap sab log....
8
4
101
4,066
Migrating from SQL to NoSQL sounds like a simple database replacement exercise. Export the data from one database, import it into another, update a few queries, and you're done. But in reality, database migrations are among the riskiest operations in system design because the database sits at the center of almost every application. A mistake during migration can impact performance, consistency, availability, and even cause permanent data loss. But why migrate at all? Traditional SQL databases like MySQL and PostgreSQL excel at handling structured data, complex joins, transactions, and strong consistency. However, as applications scale, certain workloads become difficult to handle efficiently. Social media feeds, product catalogs, recommendation systems, IoT telemetry, and large-scale user activity tracking often generate massive volumes of semi-structured or rapidly changing data. This is where NoSQL databases such as MongoDB, Cassandra, DynamoDB, or Couchbase become attractive because they are designed for horizontal scalability and flexible schemas. The biggest challenge during migration is not moving the data itself. The real challenge is changing the data model. In a SQL database, information is usually normalized across multiple tables connected through relationships. A simple user profile page might require joining data from users, addresses, orders, subscriptions, and preferences tables. NoSQL databases often favor denormalization, where related information is stored together in a single document or partition to reduce expensive joins. A common mistake is performing a "lift-and-shift" migration where the SQL schema is recreated almost identically inside NoSQL. While technically possible, this usually defeats the purpose of adopting NoSQL because the application continues behaving as if it were using a relational database. A typical migration architecture involves a dual-write or CDC mechanism. Every new update made to the SQL database is captured and propagated to the NoSQL database. Engineers continuously validate that records match in both systems. Only after confidence is built does traffic gradually shift toward the NoSQL system. One interesting question is: why not switch everything at once? Because rollback becomes nearly impossible. If a migration fails after millions of users have already started writing to the new database, recovering can become extremely complicated. Gradual migration allows teams to detect issues early and safely revert if necessary. Consistency is another important consideration. SQL databases typically provide strong ACID guarantees. Many NoSQL systems prioritize scalability and availability, sometimes using eventual consistency. This means architects must evaluate whether the application can tolerate temporary inconsistencies. Features such as banking transactions may struggle under eventual consistency, while social media likes, views, and comments often tolerate it perfectly well. Performance testing also plays a critical role. A migration that succeeds functionally may still fail under production traffic. Teams usually perform extensive load testing to validate read latency, write throughput, replication delays, hotspot behavior, and failure recovery before completing the migration. Data validation is equally important. Every migrated record must be verified to ensure correctness. Even a tiny mismatch rate can become disastrous when dealing with billions of records. Many organizations run both systems in parallel for weeks or even months before fully decommissioning the old database. Should every growing application migrate from SQL to NoSQL? The answer is no. SQL databases continue to power some of the world's largest systems. Migration should never happen because NoSQL is trendy. It should happen only when workload characteristics, scalability requirements, schema flexibility, or operational constraints justify the tradeoff.
2
1
21
1,087
What is over Engineered vs Practically Engineered? At first glance, the architecture on the left side of image looks far more impressive than the one on the right. It has microservices, Kafka, Redis clusters, Elasticsearch, service meshes, multi-region deployments, and a distributed database setup. It feels like the kind of architecture used by companies serving hundreds of millions of users. But here's the catch: the system only has 100 users. This is a classic example of over-engineering. Many developers learn exciting technologies and immediately want to use them everywhere. Microservices sound modern. Kafka sounds scalable. Kubernetes sounds production-ready. Before long, a simple application becomes a maze of services, queues, clusters, and deployment pipelines. The problem is that every component adds complexity. More services mean more codebases to maintain. More deployments mean more monitoring. More infrastructure means more operational overhead. Suddenly, developers spend more time managing the architecture than solving business problems. Now compare that with the architecture on the right. A load balancer routes traffic to a monolithic application backed by PostgreSQL and Redis. It isn't flashy. It won't impress people in a system design interview. But for 100 users, it solves the problem efficiently, costs less money, is easier to maintain, and allows developers to ship features much faster. One of the biggest myths in software engineering is that scalability must be designed on day one. In reality, most successful systems started simple. Facebook began as a monolith. Instagram served millions of users with a surprisingly small and simple architecture. Complexity was introduced only when real scaling bottlenecks appeared. A good engineer knows how to build complex systems. A great engineer knows when complexity is unnecessary. The goal of system design is not to use every technology you know. The goal is to build the simplest system that successfully solves the problem. If a monolith can handle your traffic, use a monolith. If a single database can serve your workload, use a single database. Scale only when actual metrics show that you need to. A useful principle is: Make it work → Make it reliable → Make it scale. Many teams skip directly to the scaling phase and end up creating systems that are harder to develop, harder to debug, and harder to maintain. The architecture on the left is optimized for millions of users that may never arrive. The architecture on the right is optimized for the users that actually exist today. And in system design, solving real problems is always better than preparing for imaginary ones. Happy designing ❤️
3
29
1,063
How WhatsApp ensures end-to-end Encryption? The goal of end-to-end encryption is surprisingly straightforward. The message should only be readable by the sender and the intended receiver. Not WhatsApp. Not internet providers. Not hackers. Not even the servers that carry the message across the world. The process starts when the sender wants to send a message. Before any message leaves the sender's device, it is encrypted using a public key associated with the receiver. A public key can be safely shared with anyone and is usually distributed through the messaging platform's servers. The important detail is that while anyone can encrypt data using the public key, nobody can decrypt it using that same key. Once encrypted, the message travels through WhatsApp's servers. This is where many people have a common misconception. The servers absolutely do handle the message, route it, store it temporarily if the receiver is offline, and ensure delivery. However, the servers only see encrypted ciphertext. When the encrypted message reaches the receiver, the receiver's private key is used to decrypt the content. Unlike the public key, the private key never leaves the receiver's device and is kept secret. Since only the matching private key can decrypt data encrypted with the corresponding public key, only the intended recipient can read the original message. If WhatsApp's servers help deliver the message, why can't WhatsApp simply decrypt it? Because the server only has access to public keys, which are useful for encryption but useless for decryption. The private key required to unlock the message never resides on WhatsApp's infrastructure. Even if the server wanted to read the message, it lacks the necessary cryptographic material. Another interesting challenge appears when millions of users are continuously exchanging messages. Constantly encrypting every message with asymmetric encryption alone would be computationally expensive. Modern messaging applications therefore use a hybrid approach. Public and private keys are primarily used to establish a secure session, after which much faster symmetric encryption keys are generated for actual message exchange. This provides both strong security and high performance. What happens if someone intercepts the message while it is traveling across the internet? Without encryption, the attacker could immediately read the contents. With end-to-end encryption, the attacker only sees random encrypted bytes. Since they do not possess the receiver's private key, the intercepted data is practically useless. The system also protects against many server-side breaches. Imagine a messaging company's database being compromised. Attackers may gain access to stored encrypted messages, but without the corresponding private keys, those messages remain unreadable. This significantly reduces the impact of infrastructure compromises. Messages are end-to-end encrypted, but WhatsApp know who is talking to whom because encryption protects message content, not necessarily metadata. The platform may still know information such as sender IDs, receiver IDs, timestamps, delivery status, and device information. The actual message body, remains encrypted and inaccessible to the platform. End-to-end encryption becomes even more important when messages cross multiple networks, countries, cloud providers, and data centers. Every intermediate system involved in routing the message becomes untrusted by design. Security does not depend on trusting the network. Security depends on cryptography. The fascinating part is that the internet itself was never designed to be trustworthy. Data passes through routers, ISPs, cloud infrastructure, and countless intermediate systems. End-to-end encryption solves this problem by ensuring that even if every component in the middle can see the message packet, none of them can understand its contents.
1
1
16
547
When we watch a live cricket match on Hotstar, it feels simple, open the app, click play, and enjoy the game. But behind the scenes, delivering the same ball to millions of viewers at exactly the same time is one of the toughest system design challenges in the world. Think about an IPL final or a World Cup match. The moment Virat Kohli reaches a century or a batter hits a match-winning six, millions of people open the app simultaneously. If every user request went directly to a central server, the entire system would crash within seconds. That's why streaming platforms rely heavily on CDNs (Content Delivery Networks). Instead of serving video from one location, video segments are distributed across CDN edge servers around the world. Users are connected to the nearest CDN node, reducing latency and preventing backend servers from being overwhelmed. Another interesting fact is that live video isn't streamed as one huge file. The live feed is broken into thousands of small video segments, each lasting a few seconds. Viewers continuously download Segment 1, Segment 2, Segment 3, and so on. Since millions of users request the same segments, CDN nodes cache them and serve them repeatedly without contacting the origin servers every time. During major sporting events, CDNs often become more important than the application servers themselves. Behind the CDN sits a load balancer. Its job is to distribute incoming traffic across multiple backend servers so that no single machine gets overloaded. If one server fails, traffic is automatically redirected to healthy servers, ensuring uninterrupted streaming for viewers. Traffic during live events is highly unpredictable, which is why platforms use Auto Scaling Groups. On a normal day, a few hundred thousand users may be watching. During an IPL final, that number can suddenly jump to tens of millions. Cloud infrastructure continuously monitors CPU usage, memory consumption, network throughput, active connections, and request rates. As traffic increases, new servers are launched automatically. Once the match ends and traffic drops, unnecessary servers are terminated, helping control infrastructure costs. Bandwidth is another massive challenge. A single HD stream consumes several megabits per second. Multiply that by millions of concurrent viewers, and the bandwidth requirements become enormous. To solve this, streaming platforms use adaptive bitrate streaming. Users with fast internet connections receive higher-quality video, while users on slower networks receive lower-quality streams. The system dynamically adjusts video quality based on network conditions to provide the best possible viewing experience. One of the toughest challenges is the "thundering herd problem." Imagine a match-winning six. Millions of users may refresh the stream, replay highlights, check scorecards, share clips, or open the app within seconds. These synchronized actions create sudden traffic spikes far larger than normal patterns. To handle such bursts, platforms depend on distributed caching, edge delivery, traffic shaping, queue-based processing, and rate limiting. A common question is: why not simply buy one extremely powerful server? The answer is that computing power is only a small part of the challenge. The real problems are geographic distribution, bandwidth, fault tolerance, latency, and handling millions of simultaneous connections worldwide. No single server, regardless of its power, can solve these distributed system challenges. The most fascinating part of live streaming architecture is that encoding and storing the video is often the easy part. The real challenge is delivering the same content reliably, at scale, with low latency, to millions of users simultaneously without the entire system collapsing. That's why platforms like Hotstar are not just video applications - they are some of the largest and most sophisticated distributed systems ever built. Happy designing ❤️
2
1
22
810
Aditya Tandon retweeted
Best Java Backend Series is coming on Coder Army Channel from 15th June....
6
4
60
1,553
Claude has this amazing ability to turn a simple question into a token consumption event. I just wanted an explanation, not a multimedia experience you token burner.
6
5
19
1,886
High level design of Claude Claude is designed as a multi-layered AI system where a user request does not directly reach a single transformer model, but instead passes through a carefully orchestrated pipeline of safety, formatting, reasoning, and output control stages. This layered design is necessary because modern LLM systems operate in open environments where inputs can be ambiguous, or unsafe, and outputs must remain both helpful and policy-compliant. The system starts with the User Input layer, which is the raw prompt provided by the user. This input is untrusted by default because real-world users may attempt prompt injection, ask unsafe queries, or embed hidden instructions inside otherwise normal-looking text. Because of this, the system never directly forwards the input into the model without processing. The first major stage is the Safety and Input Filtering Layer. This layer acts as a protective boundary around the model. It checks for malicious instructions, policy violations, toxic content, and prompt injection patterns. It also attempts to sanitize or neutralize parts of the input that could manipulate downstream reasoning. This ensures that the core model receives a controlled and safe version of the request rather than raw user-provided text. After filtering, the request moves into the Prompt Formatting Layer. This is where the system constructs the final structured prompt that will be given to the model. It combines system instructions, developer constraints, conversation history, and optional tool context into a single format. This step is crucial because LLMs do not just respond to user input alone but they respond to a carefully engineered prompt structure that defines behavior boundaries and context. Once the prompt is prepared, it enters the Transformer-based Blocks, which form the core reasoning engine of the system. This is the actual LLM, built using stacked self attention layers and feed forward neural networks. Inside this block, the model performs token level reasoning, builds contextual relationships between words, and generates probability distributions over the next tokens. Mechanisms like multi-head attention, residual connections, and layer normalization enable deep contextual understanding and stable training. From here, the system may branch into two important paths depending on the situation. One branch is the Tool Interface, which allows the model to interact with external systems. If the model determines that external information or computation is required, it can request tool execution such as web search, code execution, database queries, or API calls. The key idea is that the model does not directly execute these actions; instead, it delegates them to controlled tool systems and then integrates the results back into its reasoning flow. The second branch is the Safety Refusal Head, which acts as a final decision-making checkpoint for policy enforcement. Even if the transformer generates a response, this component evaluates whether the content is safe to display. If the output violates safety guidelines or contains restricted information, the system can refuse, modify, or block the response entirely. This ensures that unsafe generations do not reach the user. After these branches are resolved, the response moves into the Response Post-processing Layer. This stage refines the raw output from the model into a clean, structured, and user-friendly format. Finally, the system produces the Final Output, which is returned to the user as the response. Modern LLM systems like Claude are not single-model pipelines. The deeper design philosophy is separation of concerns. This layered separation is what allows such systems to operate reliably at scale in real-world environments where both capability and safety are equally important. In distributed AI systems, intelligence alone is not enough. Control and safety are equally critical.
4
1
33
1,626
What actually happens inside a CI/CD pipeline after a developer pushes code? Developers work on features, bug fixes, and improvements inside source control systems like Git. Agile development primarily lives in this stage because teams continuously write, review, and merge code in small iterations instead of releasing huge changes every few months. Once code is committed, the Build stage begins automatically. The CI server pulls the latest source code and converts it into a deployable artifact. Depending on the technology stack, this could be a Docker image, Java JAR, React bundle, Python package, or executable binary. The goal here is simple: verify that the application can actually be built successfully. After building comes the Integrate phase, which is where Continuous Integration truly starts. This is the point where code from multiple developers gets merged together. Individually, every developer's code may work perfectly, but integration often reveals hidden conflicts, dependency issues, version mismatches, or API incompatibilities. CI pipelines help discover these problems immediately instead of weeks later. Next comes the Test stage. This is usually the longest and most important phase of the pipeline. Automated tests validate that the system behaves correctly before any deployment occurs. These tests may include, Unit tests, Integration tests, API tests, UI tests, Security scans, Performance checks The purpose is not to prove the code is perfect. The purpose is to catch as many failures as possible before users see them. Once tests pass, the application enters the Release phase. At this point the software is considered production-ready. Release management may involve versioning, tagging, artifact storage, compliance checks, approval workflows, or business signoffs depending on organizational requirements. The next step is Deploy. This is where the software finally moves into production infrastructure. Modern deployment systems rarely replace everything at once. Instead they use strategies such as rolling updates, canary deployments, blue-green deployments, and feature flags to minimize risk. Many engineers think deployment is the final stage. It isn't. The most overlooked part of CI/CD is the Operate phase. Once software reaches production, the real testing begins. Engineers continuously monitor: * Error rates * CPU usage * Memory consumption * Request latency * User behavior * Infrastructure health * Business metrics This is where DevOps extends the CI/CD pipeline. DevOps is not just about deployment automation. It is about continuously operating, monitoring, improving, and maintaining systems after deployment. Agile Development focuses primarily on creating software. Continuous Integration focuses on validating software. Continuous Delivery focuses on preparing software. Continuous Deployment focuses on releasing software. DevOps focuses on running software. Each layer extends responsibility further into the software lifecycle. This evolution happened because modern systems are too complex for isolated teams. Developers can no longer throw code over the wall to operations teams and forget about it. Instead, engineering organizations now own the entire journey from code creation to production reliability. This shift is why elite engineering teams can deploy hundreds or even thousands of times per day while maintaining high reliability. The ultimate goal of a CI/CD pipeline is not faster deployment. The ultimate goal is reducing the time between an idea and a reliable production feature while keeping risk as low as possible. Happy designing ❤️
1
1
26
879
Let’s talk about Load Testing. Load testing simply means sending a lot of requests to a server. But real-world load testing is much deeper than that. The goal is not just to crash the application but the goal is to understand how the system behaves under stress, where bottlenecks appear, and how the architecture reacts when traffic suddenly increases. In modern distributed systems, load testing is one of the most important reliability practices because systems rarely fail during normal traffic. Most failures happen during spikes like product launches, sales, cricket match streaming, viral posts, Big billion days event or sudden traffic bursts from millions of users. Load testing helps engineers answer critical questions: Can the system survive 10x traffic? Which component breaks first? How much latency increases under pressure? Does autoscaling work correctly? Will databases throttle? Will caches start missing? Will queues start piling up? A typical load testing flow starts by identifying realistic traffic patterns. This is very important because fake unrealistic traffic gives useless results. For example, an e-commerce platform may receive mostly read requests during browsing, but during flash sales write traffic suddenly explodes because of payments, inventory updates, and order creation. That means engineers first define workloads such as: * Concurrent users * Requests per second (RPS) * Read vs write ratio * File upload sizes * Peak traffic windows * Geographic distribution * Mobile vs web traffic After defining workloads, engineers simulate traffic using load testing tools like JMeter, k6, Gatling, or Locust. These tools create thousands or millions of virtual users that continuously hit APIs, databases, queues, or web pages. But the most important part is not generating traffic. The real value comes from observing the system during stress. During load testing, teams monitor: * CPU usage * Memory consumption * Disk I/O * Database query latency * Cache hit ratio * Queue lag * Network bandwidth * Error rates * Request timeout percentage * Autoscaling behaviour Sometimes the application server is perfectly healthy, but the database connection pool becomes exhausted. Sometimes databases survive, but the cache layer starts missing heavily. Sometimes the infrastructure survives but latency becomes unacceptable for users. This is why load testing is actually a bottleneck discovery process. There are multiple types of load testing in system design. Normal load testing checks expected production traffic. Stress testing pushes the system beyond limits to find breaking points. Spike testing suddenly increases traffic rapidly to observe recovery behaviour. Endurance testing runs traffic for hours or days to identify memory leaks, resource exhaustion, or slow degradation. Chaos load testing combines heavy traffic with failures like node crashes or network delays to test resilience. One very important concept during load testing is throughput vs latency. A system may technically handle 1 million requests per minute, but if response time becomes 15 seconds, the system is practically unusable. Good systems maintain stable latency even during high traffic. This is why engineers usually define SLOs (Service Level Objectives), such as: * 95% requests under 200 ms * Error rate below 1% * Database CPU below 70% * Cache hit ratio above 90% Load testing also validates autoscaling systems. Many companies assume autoscaling will save them automatically. But during real traffic spikes, new servers may take time to boot, containers may fail health checks, databases may not scale quickly enough, or rate limiters may start rejecting users. Without load testing, these issues remain hidden until production traffic exposes them publicly. This is why large-scale companies continuously perform load testing before major launches. Because once production traffic arrives, there is no safe environment left to experiment.
2
26
681