Measure first, then fix the slowest part of the request path. Track latency percentiles such as the 99th alongside error rates, because an average hides the slow tail users notice. Distributed tracing and APM tools show where each slow request spends its time.
The database is the usual bottleneck. Index the columns your queries filter and join on, and check slow queries with EXPLAIN. Fix N+1 queries, where a loop runs one query per item, with a join or one batched query. Connection pooling avoids a new connection per request. Read replicas spread read load, but they can lag, so reads that must see a fresh write go to the primary.
Caching skips the work. Keep hot data in Redis with a TTL, and clear it when the data changes. Send Cache-Control and ETag headers, so clients, CDNs and an API gateway can reuse responses. An unchanged resource then comes back as a bodiless 304 Not Modified.
Then shrink the response. Field selection lets a client ask only for what it needs, as in GET /users?fields=id,name,email. Compress responses with gzip, paginate long lists, and leave related resources out until the client asks for them.
Move heavy work off the request path. Async processing and background job queues let the API answer at once with 202 Accepted. Splitting into microservices helps scaling, not latency, because every remote call adds a network hop.
This answer doesn't lend itself to a diagram - it reads best . No credits were charged.
Why there's no diagram: “”
The interactive diagram is below the answer - jump to diagram ↓ · Below it, the related concept . Jump to it ↓
The diagram below the answer is the concept . Jump to it ↓