LLM Response Speed Innovation Guide: Architecture Design to Reduce Perceived Latency with Streaming and Caching
"How long is this going to take?"
If you've recently used modern AI interfaces like Copilot or ChatGPT, you've probably forgotten the concept of "waiting" altogether. Responses don't drop all at once; they appear on the screen character by character in real time, as if a person were typing.
This is the core variable that determines the success of LLM services: perceived latency.
In Part 1 we covered cost efficiency for LLM services and laid the first foundation of architecture design. In this Part 2 we focus on the next step: user experience (UX) optimization. No matter how smart and inexpensive the model, if a response takes 5 seconds, users will get bored and leave.
This post is not simply about "how to make it faster." It presents a practical architecture design roadmap that makes users feel "this service is fast and responsive."
🚀 1. Why LLM Response Speed Is Critical to Service Success (Problem Statement)
When discussing AI service performance metrics, many people focus on accuracy or throughput. Those matter, of course. From the user's perspective, however, the first thing they feel is speed.
UX research shows that users begin to experience cognitive fatigue when a response is delayed by more than 0.5 seconds, and the likelihood of abandonment rises sharply after 3 seconds.
The goal is to reduce both actual latency and perceived latency. The two key weapons for doing so are streaming and caching.
✨ 2. The Magic of Overcoming Latency: Streaming Implementation
Traditional API calls are like receiving an entire report at once. The client sees nothing until the server has generated every token, and only then receives the complete result.
Streaming changes this fundamentally. Like a radio, it is a mechanism that sends tokens to the client as soon as they are generated.
Streaming Principle: Real-Time Token-Level Transmission
Streaming processes LLM API calls asynchronously and continuously pushes intermediate results to the client.
🛠️ Technical Implementation: Using SSE (Server-Sent Events)
The most suitable technology for continuously sending unidirectional data from the backend to the client is Server-Sent Events (SSE). WebSockets can also work, but SSE is optimized for simple data-stream transmission, so implementation complexity is lower and the approach is more intuitive.
💡 Conceptual Code Flow for SSE-Based Streaming (Python/Flask Example)
from flask import Response
def generate_stream():
# LLM reply when
messages = [".", "", "AI architecture .", " ."]
for i, message in enumerate(messages):
# 'data: ' \r\n\r\n quit when
yield f"data: {message} ({i+1}/{len(messages)})"
# when
import time; time.sleep(0.2)
@app.route('/stream-response')
def stream_response():
return Response(generate_stream(), mimetype='text/event-stream')Practical tip: Error handling and disconnection
The biggest enemy of streaming is dropped connections. On the client, you must implement an onerror handler that includes reconnection logic. On the server, configure timeouts to prevent infinite loops or abnormal termination.
🛡️ 3. Instantly Handling Repeated Requests: Applying Caching Strategies in Depth
If streaming improves the "feel," caching brings actual wait time close to zero. LLM services, however, need caching strategies different from ordinary database lookups.
🧠 Two LLM-Specific Caching Strategies
1. Prompt Caching
The most common and effective approach. When the same input prompt arrives, the previously computed response is reused.
- Use case: FAQ questions such as "What is our company's vacation policy?"
- Implementation: Use an in-memory database such as Redis.
🔑 Example Redis Data Structure for Prompt Caching:
| Key | Value | Expiration |
|---|---|---|
prompt:faq:holiday_rule | {"response": "Annual leave is 15 days, and prior approval is required.", "model_version": "gpt-4o"} | 1 hour |
2. Response Caching
This caches the final response itself rather than the prompt. It allows the LLM call to be skipped entirely.
- Use case: Summaries of specific topics or answers based on a fixed knowledge base.
- Caveat: This approach can be sensitive to even minor prompt variations, so when constructing the cache key it is essential to hash and combine core elements of the prompt (key keywords, user ID, etc.).
⚠️ Practical tip: Designing a cache invalidation strategy
The hardest part of caching is deciding when to invalidate. Use a Cache-Aside pattern that refreshes the cache when data changes. For example, when a new policy is added to the FAQ database, you must include logic that forcibly deletes (DELETE) the corresponding cache key.
💡 Summary Comparison:
| Strategy | Purpose | Advantages | Disadvantages |
|---|---|---|---|
| Streaming | Improve user experience | Maximize perceived speed (reduce perceived latency) | Potential increase in server load |
| Caching | Cost and speed optimization | Reduce API call costs, maximize response speed | Risk of data inconsistency (stale data) |
🚀 Conclusion: Optimal Architecture Design
The most ideal architecture combines streaming and caching.
- Request received: The user sends a request.
- Cache check: The system first checks whether a response for that request exists in the cache (Redis, etc.).
- Cache hit: Immediately send the cached response to the user via streaming. (Fastest)
- Cache miss: a. Call the LLM API. b. Send the API response to the user via streaming. (The user does not feel like they are waiting.) c. Once the response is complete, store the result in the cache.
This process gives users the fastest perceived speed while also delivering cost efficiency from an operations standpoint.
Sources and checks vary by article. Only articles with a recorded check date, scope and sources below were checked, and only within that scope. For other articles, verify against the current docs for your version before applying anything, and email us about errors. Editorial policy · email us
This article has no recorded human check (date and scope) yet.
Comments
Be the first to comment.