Katerina Sh ← All work
Case Study Performance · Backend

API Caching & Processing Optimization

Improving API performance by reusing previously generated results when fresh processing is not required.

Request path reuse or process
API request
Can an existing result be reused?
yes
Return cached result
no
Run fresh processing
Role
Backend Developer
Project type
Commercial Backend Experience · Public Technical Demonstration
Tech stack
C#.NETASP.NETPostgreSQLApplication CachingDependency InjectionRedisEF CoreDocker
01 — Delivered

What I delivered

  • Implemented caching for expensive processing results in a commercial backend system
  • Added logic to determine when an existing result could be safely reused
  • Prevented unnecessary repeated processing when meaningful input had not changed
  • Preserved fresh processing whenever cached data was unavailable or no longer valid
  • Kept caching concerns separated from core business logic
  • Built a separate public .NET project demonstrating related multi-layer caching principles
02 — Overview

This work combines real commercial experience with a separate public implementation.

In the commercial system, I implemented caching around an API workflow that produced reusable results through a more expensive processing path. The goal was to avoid repeating the same work when an existing result was still valid.

To demonstrate related backend principles publicly without exposing private code or business logic, I later built a standalone .NET API using memory cache, Redis, and PostgreSQL.

03 — Context

The problem

Some API operations depended on a multi-step processing workflow.

Running the complete workflow for every request created unnecessary work when the underlying data affecting the result had not meaningfully changed.

At the same time, the system could not simply reuse every previous response. It needed to distinguish between cases where an existing result remained valid and cases where fresh processing was required.

04 — Approach

Solution

I implemented input-aware result caching for the commercial API workflow.

Previously generated results could be reused when the data affecting the outcome remained unchanged. When meaningful input changed, when no reusable result was available, or when the cached value could no longer be considered valid, the system continued through the normal processing flow.

The caching logic was kept separate from the core business logic so that the workflow remained maintainable and the processing path stayed clear.

A separate public project demonstrates the broader caching approach through a layered read flow:

Cache hierarchy read path
Memory cache fastest
Redis distributed
PostgreSQL source of truth
05 — Architecture

How it fits together

The commercial implementation introduced a cache decision before the more expensive processing stage. The public demonstration extends the idea into a layered hierarchy.

Commercial request flow
API request
Determine whether an existing result can be reused
Return cached result or continue with fresh processing
Read flow · public demo
Memory cache
Redis
PostgreSQL
Write flow · public demo
Persist data
Refresh Redis
Refresh memory cache

The public project demonstrates related architectural principles but does not reproduce the commercial system or its proprietary workflow.

06 — Features

Key features

Input-aware result caching

Reuse of previously generated outputs

Conditional execution of expensive processing

Cache validity checks

Clear fallback to fresh processing

Separation of caching and business logic

Multi-layer caching in the public implementation

PostgreSQL persistence

Redis distributed cache

Docker-based local setup

OpenAPI documentation

07 — Challenges

Technical challenges

The main challenge was defining when a previously generated result was still valid.

A cache hit could not be based only on the presence of an existing value. The system also needed to account for whether the data affecting the result had meaningfully changed.

The implementation had to avoid two opposite problems:

  • repeating expensive processing when the previous result was still valid;
  • returning stale data when fresh processing was required.

Another important consideration was keeping the caching logic isolated so that it did not spread through the business workflow or make the application tightly dependent on a specific cache implementation.

08 — Outcome

Outcome

The commercial implementation reduced unnecessary repeated processing and created a faster path for requests that could safely reuse an existing result.

It also preserved the original processing flow for cases where a new result was required.

The accompanying public project provides inspectable code and a reproducible environment demonstrating related caching, data-access, and separation-of-concerns principles without exposing commercial code, internal services, or proprietary business logic.

Have a similar performance problem?

Tell me about the system you want to make faster and more predictable.

Start a project  ↗ Back to all work
Katerina Sh · Full-Stack Engineer © 2026 Ninja Paws · All rights reserved