Deepak Kumar Singh

The full-stack journey, and the ideas behind it

A sub-universe of this portfolio: the career read as a stack, interactive models of the concepts that matter, and simulated live-production scenarios.

Monolith to microservices: reference patterns

These are generic reference patterns, the shapes this kind of modernization usually takes. They are not diagrams of any real system, and every number in the simulators is invented for teaching.

Reference pattern 1: modernizing a coupled enterprise application

A monolith shares one database and makes blocking calls between its parts, so a slow report, a long onboarding step or one noisy tenant slows everyone. The usual target is a small set of domain services behind a gateway, with events at the boundaries and a cache where reads dominate.

Legacy monolith state

One deployable unit. Every feature shares one database and one connection pool. Calls between modules are synchronous, so a slow step blocks the request that triggered it. Onboarding a new client means a long, manual, tightly coupled setup that touches the whole application.

Legacy monolith stateParts: Client, Monolith (UI + logic), One shared database. Client to Monolith (UI + logic) (a blocking call); Monolith (UI + logic) to One shared database (a blocking call).ClientMonolith(UI + logic)One shareddatabase
Solid line: a blocking call. Dashed line: an asynchronous event. Dotted line: an automated release.

Target microservices state

Domain services (identity, onboarding, reporting) own their data and scale independently. A gateway fronts them, long work moves behind asynchronous events, a cache absorbs repeated reads, and onboarding becomes an automated, repeatable pipeline.

Target microservices stateParts: Client, API gateway, Identity service, Onboarding service, Reporting service, Deployment pipeline, Event bus, Read cache. Client to API gateway (a blocking call); API gateway to Identity service (a blocking call); API gateway to Onboarding service (a blocking call); API gateway to Reporting service (a blocking call); Onboarding service to Event bus (an asynchronous event); Event bus to Reporting service (an asynchronous event); Reporting service to Read cache (a cached read); Deployment pipeline to Onboarding service (an automated release).ClientAPI gatewayIdentityserviceOnboardingserviceReportingserviceDeploymentpipelineEvent busRead cache
Solid line: a blocking call. Dashed line: an asynchronous event. Dotted line: an automated release.

What gains come from which part

  • −30% backend response time (reported on the experience page) In a pattern like this, response time usually falls for three reasons: reads move to a cache instead of the shared database, slow work leaves the request path behind an event, and each service scales on its own instead of with the whole application. Parts involved: API gateway, Read cache, Reporting service, Event bus.
  • −20% client onboarding time (reported on the experience page) Onboarding gets faster when it is its own service with an automated, repeatable deployment pipeline, instead of a manual procedure that touches the whole application. Parts involved: Onboarding service, Deployment pipeline, Identity service.
  • Smaller blast radius (a property of the pattern) With separate data and asynchronous boundaries, a failure or a slow query in one domain no longer stalls the others. Parts involved: Identity service, Onboarding service, Reporting service, Event bus.

Reference pattern 2: keeping a busy public portal up under a spike

A public portal can see ordinary load for weeks and then a sudden spike, often with many people competing for the same record at once. Four patterns do most of the work of staying up: pooling connections, locking optimistically, caching reads and isolating faults. Switch them on and off and watch what a spike does.

The four patterns

Connection pooling
A bounded pool of reusable database connections, so a spike queues briefly instead of opening thousands of connections and exhausting the database.
Optimistic locking
Many users contend for the same record. Each writer reads a version, and only the first to write wins; the rest retry or are told, with no long-held row locks.
Caching layer
Repeated reads are served from memory, so the database mostly sees writes.
Fault isolation
Bulkheads and timeouts keep one slow dependency from tying up every worker thread.

What the model says at 8 times normal traffic

The same spike, with different protections switched on
Protections onSlowest momentWorst second: requests failingUptime in the windowOverloaded part
No protections10 s or more100%38%Database
Caching only10 s or more100%40%Worker threads
Pool, cache and optimistic locking3.0 s50%43%Worker threads
All four patterns53 ms0.0%100%None

How the model works

  • Normal traffic is 100 requests a second. The spike ramps up over 10 seconds, holds for 15 and ramps down over 10, inside a 60 second window. It is 8 times normal by default.
  • 80% of requests are reads, and half of the writes aim at one hot record.
  • Worker capacity is 400 requests a second while a slow dependency can tie up threads, and 1,500 when it is isolated by a timeout and a bulkhead.
  • Database capacity is 450 operations a second, and a cache answers 92% of reads.
  • One hot record takes 45 writes a second under row locks and 260 with optimistic versions, which cost a few retries.
  • Without a bounded connection pool, too many connections slow the database itself. With a pool, extra requests wait in a queue of 300 or are turned away; without one the queue grows to 3,000.
  • A request slower than 5 seconds fails. A second counts toward uptime only if latency is under 2 seconds and under 2% of requests fail.

Try it: the spike simulator

Where high availability comes from

  • 99.9% uptime (reported on the experience page) In a pattern like this, high availability under a spike comes from all four working together: no single one is enough.

These are generic reference patterns, the shapes this kind of modernization usually takes. They are not diagrams of any real system, and every number in the simulators is invented for teaching. Every host, request count and timing in this lab is invented for teaching.

The same ideas on the 3D map: the Full-Stack Universe, its production scenarios, and the experience section of the map.

The concept chapters, the machine-level chapters and the production scenarios are teaching models and simulations with invented numbers, labelled as such on the site. They are not records of real incidents. The journey below is taken from the role descriptions on this site.

The journey: six roles

Concepts

Inside the machine

CPU, virtual memory, RAM, swap and the out-of-memory killer, and where programs become vulnerable.

Production scenarios

Simulated incidents to diagnose and fix.

Open the interactive version.