📘 System Design - Concepts

Performance in System Design

Performance describes how quickly and efficiently a system responds to requests and completes its work.

S

Site Administrator

📅 Sep 26, 2026 🕒 6 min read 👁 24 views
☆ Save 𝕏 in f ✆
Performance in System Design

Performance describes how quickly and efficiently a system responds to requests and completes its work.

Imagine opening a shopping application and waiting 10 seconds for a product page to load. The application may be available and reliable, but the user experience is still poor.

Performance is therefore an important part of System Design.

What Is Performance?

Performance is mainly concerned with questions such as:

  • How quickly does the system respond?
  • How many requests can it process?
  • How much CPU and memory does it use?
  • How quickly can the database execute queries?
  • How efficiently does the system use network and storage resources?

For example, suppose an API normally responds in 200 milliseconds.

If the same API starts taking 5 seconds during high traffic, there is a performance problem.

Real-World Example

Consider an e-commerce application.

A customer searches for a mobile phone.

flowchart LR
    User --> API
    API --> Database
    Database --> API
    API --> User

The request may involve several operations:

  • Receive the request.
  • Validate the request.
  • Execute a database query.
  • Process the result.
  • Return the response.

If any of these operations is slow, the total response time increases.

Latency

Latency is the time taken for an operation to complete or for a response to be received.

For example:

Client → API = 20 ms
API → Database = 50 ms
Database processing = 80 ms
API processing = 20 ms
Response = 20 ms

The total time is approximately 190 milliseconds.

Reducing unnecessary work in any part of the request can improve the overall response time.

ASP.NET Core Example

Consider this API:

[HttpGet]
public async Task GetEmployees()
{
    var employees = await _context.Employees
        .ToListAsync();

    return Ok(employees);
}

This works, but suppose the Employees table contains millions of records.

Returning every employee in one response can consume significant database, memory and network resources.

A better approach is pagination.

[HttpGet]
public async Task GetEmployees(
    int page = 1,
    int pageSize = 20)
{
    var employees = await _context.Employees
        .AsNoTracking()
        .OrderBy(x => x.Id)
        .Skip((page - 1) * pageSize)
        .Take(pageSize)
        .ToListAsync();

    return Ok(employees);
}

Now the API returns only the required records.

SQL Server Performance

Database queries are often an important part of application performance.

Consider this query:

SELECT *
FROM Employees
WHERE Department = 'IT';

If the table contains millions of rows and Department is not indexed appropriately, SQL Server may need to examine a large amount of data.

An index can help:

CREATE INDEX IX_Employees_Department
ON Employees(Department);

Now SQL Server can use the index to find matching records more efficiently.

Do Not Return Unnecessary Data

Another common performance problem is retrieving more columns than the application actually needs.

Instead of:

var employees = await _context.Employees
    .ToListAsync();

we can select only the required fields:

var employees = await _context.Employees
    .Select(x => new
    {
        x.Id,
        x.Name,
        x.Department
    })
    .ToListAsync();

This can reduce the amount of data transferred from the database.

Use Caching

Suppose product information is requested thousands of times but changes only occasionally.

Querying SQL Server for every request may be unnecessary.

A cache can store frequently requested data.

flowchart TD
    Request --> Cache
    Cache --> Found
    Found --> Response
    Found --> Database
    Database --> Cache
    Cache --> Response

When data is available in the cache, the application can return it without querying the database.

This can reduce database load and improve response time.

Database Connection Management

Applications communicate with SQL Server using database connections.

Creating unnecessary connections can hurt performance.

ASP.NET Core applications using Entity Framework Core normally rely on connection pooling and dependency injection to manage database connections efficiently.

For example:

builder.Services.AddDbContext(options =>
    options.UseSqlServer(connectionString));

Connection pooling allows existing database connections to be reused instead of creating a completely new connection for every operation.

Async Programming

ASP.NET Core applications commonly use asynchronous operations for I/O work.

For example:

var employees = await _context.Employees
    .AsNoTracking()
    .ToListAsync();

Using asynchronous database calls allows the application to avoid blocking a thread while waiting for SQL Server to respond.

This becomes particularly useful when the application handles many concurrent requests.

External API Performance

Suppose our application calls a payment service.

flowchart LR
    User --> API
    API --> PaymentService
    PaymentService --> ExternalAPI
    ExternalAPI --> PaymentService
    PaymentService --> API
    API --> User

If the external API takes 5 seconds to respond, our API may also become slow if we wait synchronously for it.

We should consider:

  • Timeouts
  • Asynchronous processing
  • Caching where appropriate
  • Connection reuse
  • Retry policies for suitable failures

Move Slow Work to Background Processing

Not every operation needs to happen before returning the API response.

Suppose a user places an order and we need to send an email notification.

We may not need to make the user wait for the email to be sent.

flowchart LR
    User --> OrderAPI
    OrderAPI --> Database
    OrderAPI --> Queue
    Queue --> NotificationService
    NotificationService --> Email

The API can save the order and place a message on a queue. A background service can process the notification later.

This can reduce the response time experienced by the user.

Performance Bottlenecks

When an application becomes slow, we should not immediately add more servers.

First, identify the bottleneck.

It could be:

  • Slow SQL query
  • Missing database index
  • Large response payload
  • High CPU usage
  • Memory pressure
  • Network latency
  • External API latency
  • Too much application processing
  • Locking or blocking in the database
flowchart TD
    SlowAPI --> CheckApplication
    SlowAPI --> CheckDatabase
    SlowAPI --> CheckNetwork
    SlowAPI --> CheckExternalService

    CheckApplication --> FindBottleneck
    CheckDatabase --> FindBottleneck
    CheckNetwork --> FindBottleneck
    CheckExternalService --> FindBottleneck

Monitoring Performance

Performance should be measured rather than guessed.

Useful metrics include:

  • Average response time
  • 95th percentile latency
  • 99th percentile latency
  • Requests per second
  • CPU usage
  • Memory usage
  • Database query duration
  • Error rate

For example, an average response time of 100 milliseconds may look good, but if 5% of requests take 5 seconds, users can still experience poor performance.

Performance vs Scalability

Performance and scalability are related but different.

Performance asks:

How quickly and efficiently can the system handle its current workload?

Scalability asks:

Can the system continue handling increasing workload as demand grows?

A system can be very fast for 1,000 users but fail when traffic increases to 1 million users.

Key Takeaways

  • Performance is about how efficiently and quickly a system works.
  • Slow database queries can become major performance bottlenecks.
  • Indexes can improve database query performance.
  • Pagination prevents unnecessarily large responses.
  • Selecting only required columns reduces data transfer.
  • Caching can reduce repeated database operations.
  • Async I/O helps ASP.NET Core handle concurrent requests efficiently.
  • Background processing can keep slow operations out of the main request path.
  • Always measure performance and identify the actual bottleneck.

Conclusion

Performance is not about making only one part of an application fast.

We need to look at the complete request path, including the API, database, cache, network and external services.

Good performance comes from reducing unnecessary work, optimizing database operations, controlling payload sizes, using caching where appropriate and moving suitable long-running work to background processing.

But one question still remains: How many requests can our system actually handle?

That leads to the next concept: Latency vs Throughput.

Comments & Ratings (0)

Log in or create a student account to comment and rate this article.

Be the first to comment on this article.

Never miss a new post 📬

Get an email whenever a new article, project, cheatsheet or video drops.

✅

ℹ️