DEV Community

Saras Growth Space
Saras Growth Space

Posted on

LLD Data Structures in Design Context: Why Some Work Shouldn't Happen Immediately

"One of the biggest shifts from writing code to designing systems is realizing that not everything needs to happen right now."

When we build our first applications, most of our code is synchronous.

A user clicks a button.

The application processes the request.

The user waits.

The application returns a response.

This approach works well for small applications.

But as systems grow, making users wait for every piece of work quickly becomes a problem.

Experienced software engineers constantly ask themselves an important question:

Does the user really need to wait for this?

If the answer is no, the system can often be designed in a much better way.

This is where asynchronous thinking begins.


Let's Start With an Online Shopping Example

Imagine you're building an e-commerce application.

A customer places an order.

What absolutely must happen before the customer receives a response?

Place Order

↓

Validate Order

↓

Reserve Inventory

↓

Create Order

↓

Return "Order Confirmed"
Enter fullscreen mode Exit fullscreen mode

The customer now knows the order has been placed successfully.

But the application still has plenty of work remaining.

  • Send confirmation email
  • Generate invoice
  • Notify the warehouse
  • Update analytics
  • Record business metrics
  • Recommend related products

Should the customer wait for all of this?

Probably not.


The Cost of Doing Everything Immediately

Now imagine the application performs every task before sending the response.

Place Order

↓

Validate Order

↓

Reserve Inventory

↓

Create Order

↓

Generate Invoice

↓

Send Email

↓

Notify Warehouse

↓

Update Analytics

↓

Return Response
Enter fullscreen mode Exit fullscreen mode

The customer keeps waiting while several independent tasks finish.

None of those additional tasks determine whether the order was successfully placed.

Yet they increase the response time.

From the customer's perspective, the website simply feels slow.


Another Example: Banking

Suppose you're transferring money using a banking application.

The customer expects one thing:

Did my money transfer succeed?

The critical work looks like this.

Validate Account

↓

Transfer Money

↓

Update Account Balance

↓

Return Success
Enter fullscreen mode Exit fullscreen mode

Now think about everything else.

  • Send SMS
  • Send email
  • Generate statement
  • Update analytics
  • Notify budgeting services

These tasks are valuable.

But none of them should delay the confirmation of the transfer.


Think Like an Experienced Engineer

Beginners often ask:

"What are all the tasks my application needs to perform?"

Experienced engineers ask a different question.

"Which tasks must finish before the user can continue?"

That small change in thinking leads to dramatically better system designs.

Instead of treating every task equally, they separate business-critical work from supporting work.


Critical Work vs Background Work

Whenever you're designing a feature, divide the work into two categories.

Critical Work

This work must complete before responding.

Examples include:

  • Authenticating a user
  • Processing a payment
  • Reserving a movie seat
  • Saving an order
  • Updating an account balance

Without these steps, the business operation hasn't actually succeeded.


Background Work

This work can safely happen later.

Examples include:

  • Sending emails
  • Sending notifications
  • Updating analytics
  • Generating invoices
  • Logging events
  • Updating recommendation systems

These tasks improve the overall system but don't determine whether the user's primary request succeeded.


The Request Path Is Precious

One useful mental model is to imagine the user's request travelling through your application.

User Request

↓

Business-Critical Work

↓

Response To User
Enter fullscreen mode Exit fullscreen mode

Everything inside this path directly affects how long the user waits.

Every additional task you place here increases response time.

Good engineers protect this path carefully.

Anything that doesn't belong here is a candidate for background processing.


Why This Matters as Systems Grow

Imagine a shopping platform during a festival sale.

Thousands of customers are placing orders every minute.

If every order waits for:

  • email delivery,
  • invoice generation,
  • analytics updates,
  • warehouse notifications,

then even a temporary slowdown in one supporting service affects the customer's experience.

The application becomes tightly coupled.

One slow component slows everything else.

That's not a scalability problem.

It's a design problem.


How This Changes Your LLD Design

When designing a feature, don't immediately think about classes or APIs.

Start by identifying responsibilities.

Order Service

↓

Business-Critical Work

↓

Respond To Customer

↓

Background Work
Enter fullscreen mode Exit fullscreen mode

Once you've separated these responsibilities, your design becomes much cleaner.

The service responsible for placing orders no longer needs to handle emails, reports, analytics, and notifications itself.

Each responsibility can evolve independently.

That's one of the key goals of good Low-Level Design.


Common Beginner Mistakes

Mistake 1 — Doing Everything Before Responding

Not every task belongs in the user's request path.

Always separate essential work from supporting work.


Mistake 2 — Assuming Fast Code Solves Everything

Even efficient code creates poor user experiences if unnecessary work blocks the response.

Reducing waiting time is often more valuable than reducing execution time.


Mistake 3 — Treating Every Task as Business-Critical

Many tasks improve the system without affecting the success of the user's request.

Recognize the difference.


Mistake 4 — Forgetting to Identify Responsibilities

If one service performs ordering, notifications, analytics, reporting, and logging, it's probably doing too much.

Separating responsibilities usually leads to a simpler and more maintainable design.


Engineering Perspective

Whether you're reviewing a production system or solving an LLD interview question, experienced engineers naturally ask:

  • Which work is business-critical?
  • Which work can safely happen later?
  • Which responsibilities should belong to different components?

Those questions often shape the architecture long before any technology or data structure is chosen.


The Most Important Insight

The goal of system design isn't to complete every task before responding.

It's to complete only the work that the user is actually waiting for and postpone everything else that can safely happen later.

That simple idea is the foundation of asynchronous system design.


One-Line Takeaway

Great software engineers don't make users wait for every task—they make users wait only for the tasks that truly matter.

Top comments (0)