Skip to content

🚀 Optimization - Queries & API Profiling

The Senior Mindset: “Premature optimization is the root of all evil” (Donald Knuth). A senior engineer only optimizes after measuring. We don’t guess where the bottleneck is; we use profilers and execution plans to find the exact line of code or database scan that is costing us time.


The database is usually the most expensive part of your infrastructure. Optimizing here yields the highest ROI.

Before changing a query, you must run EXPLAIN ANALYZE (Postgres/MySQL).

  • Seq Scan (Sequential Scan): The DB is reading the entire table. This is a red flag for missing indexes.
  • Index Scan: The DB is using an index. Good, but check if it’s a “Bitmap Index Scan” or “Covering Index.”
  • Nested Loops vs. Hash Joins: Understand how the DB joins tables. Large tables joined via nested loops can be devastatingly slow.

Occurs when you fetch a list of items and then perform a separate query for each item’s details.

  • The Fix: Use JOIN or IN (...) clauses in SQL. In ORMs, use “Eager Loading” (e.g., include in Prisma, select_related in Django).
  • Offset/Limit: Fine for small datasets. For millions of rows, OFFSET 1000000 is slow because the DB must still scan those million rows.
  • Keyset Pagination (Cursor): Use WHERE id > last_seen_id LIMIT 20. This allows the DB to jump directly to the index entry.

⏱️ API Profiling & Bottleneck Identification

Section titled “⏱️ API Profiling & Bottleneck Identification”

If the DB is fast, but the API is slow, you need to profile the application code.

Use Distributed Tracing (OpenTelemetry, Jaeger) to see exactly where time is spent:

  • Network Latency: Time spent traveling to the server.
  • Middleware: Logging, Auth, and Validation overhead.
  • Business Logic: CPU-bound tasks (serialization, encryption).
  • Downstream Calls: Waiting for third-party APIs or Microservices.
  • CPU-Bound: The code is doing heavy math or data processing. Solution: Optimize algorithms or use worker threads/separate services.
  • I/O-Bound: The code is waiting for a database or network. Solution: Use asynchronous I/O, caching, or connection pooling.

Tool TypeExamplesUse Case
APM (Application Performance Monitoring)New Relic, DatadogReal-time monitoring of production performance.
Language Profilerspprof (Go), cProfile (Python), Chrome DevTools (Node.js)Finding the exact function consuming CPU/Memory.
Benchmarkingk6, ab (Apache Benchmark)Stress testing an API to find its “breaking point.”
TracingHoneycomb, JaegerVisualizing how a single request travels through multiple microservices.

In high-traffic APIs, converting JSON to objects and back can consume 20-30% of CPU.

  • Senior Move: Switch to Protocol Buffers (gRPC) or MessagePack for internal service-to-service communication to reduce serialization latency.

Creating a new TCP/TLS connection for every DB query is a performance killer.

  • Senior Move: Implement a persistent connection pool (e.g., PgBouncer for Postgres) to keep connections “warm” and ready for reuse.

Don’t optimize for the “Average” (Mean). Optimize for the p99.

  • If your average response time is 100ms, but your p99 is 5s, 1% of your users (usually your most active ones) are having a terrible experience. This is often caused by Garbage Collection pauses or “Hot Keys” in the cache.

💡 Seniority Note: Sometimes the best optimization is deleting data. A table with 1 billion rows is inherently harder to optimize than one with 10 million. Implement data retention policies and archive old data to “Cold Storage” to keep your “Hot Path” fast.


  • [[Relational-Databases-Indexing]]
  • [[Caching-Redis-CDN]]
  • [[Architecture-Resilience-Patterns]]