← Back to list

Big O Notation: Understanding Complexity Beyond Definitions

After years of debugging systems, optimizing critical paths, and answering questions such “Why is this suddenly slow in production?”, I’ve…

Saif eddine hasnaoui in SoftwareCraft Mastery · 2026-01-05 15:39 · 0 claps · 4.7 min read
#algorithms #software-engineering #software-development #web-development #software-architecture
Open on Medium ↗
Wiki topics: CRY · Crypto & Web3 💻 · Programming 🌐 · Web Development 🏛️ · Architecture

Big O Notation: Understanding Complexity Beyond Definitions

After years of debugging systems, optimizing critical paths, and answering questions such “Why is this suddenly slow in production?”, I’ve learned that performance problems rarely start in production. They start in code design. And at the center of that design sits a concept every software engineer has heard of — but many don’t fully grasp:

Big O complexity.

This article isn’t another academic explanation of Big O. It’s a practical, experience-driven perspective on why Big O matters, when it matters, and how senior engineers actually use it.

Big O Complexity

Big O notation is a mathematical shorthand used to describe how an algorithm’s resource usage grows as the input size increases.

It focuses on growth behavior, not exact execution time.

More precisely:

  • Big O expresses the upper bound of an algorithm’s complexity
  • It describes the worst-case scenario as input size (n) grows

It can apply to:

  • Time complexity → how execution time grows
  • Space complexity → how memory usage grows

Big O deliberately ignores:

  • Hardware differences
  • Programming language optimizations
  • Constant factors

Why?

Because none of those matter when your input size grows large enough.

As engineers, we use Big O to answer one critical question:

Will this approach still work when the system scales?

O(1) — Constant Time

No matter how big the input is, this takes the same time.

Example:

// Accessing an array index

function getFirstUser(users: string[]) {
  return users[0];
}
  • Reading a value from a hash map

This is gold. Aim for it where possible.

O(log n) — Logarithmic Time

The input grows fast, but the work grows slowly.

Example:

// Binary search: each step cuts the problem in half.
function binarySearch(sortedNumbers: number[], target: number): number {
  let left = 0;
  let right = sortedNumbers.length - 1;

  while (left <= right) {
    const mid = Math.floor((left + right) / 2);

    if (sortedNumbers[mid] === target) return mid;
    if (sortedNumbers[mid] < target) left = mid + 1;
    else right = mid - 1;
  }

  return -1;
}
  • Or, balanced tree lookups, ..etc.

This is what scalability feels like when done right.

Senior insight: Logarithmic algorithms are why systems like databases and search engines scale so well.

O(n) — Linear Time

Work grows directly with input size.

Example:

  • Iterating through a list once
function findUser(users: string[], name: string): boolean {
  for (const user of users) 
    if (user === name) return true;

  return false;
}

This is usually acceptable — and unavoidable.

Senior insight: O(n) is usually acceptable , but only when it happens once, not inside another loop or hot path.

O(n log n) — Efficient but Non-Trivial

You’re doing real work, but in a smart way.

Example:

function sortUsers(users: string[]): string[] {
  return users.sort();
}
  • Or, efficient data processing pipelines, ..etc.

Most modern sorting algorithms (like Timsort or Merge Sort) operate at O(n log n).

Senior insight: This is often the best practical complexity for large datasets when ordering is required.

O(n²) — Quadratic Time

For every item, you scan everything again.

Example:

function findDuplicates(numbers: number[]): number[] {
  const duplicates: number[] = [];

  for (let i = 0; i < numbers.length; i++) {
    for (let j = i + 1; j < numbers.length; j++) {
      if (numbers[i] === numbers[j]) {
      duplicates.push(numbers[i]);
      }
    }
  }

  return duplicates;
}
  • Or nested loops over the same collection, comparing every element to every other element, ..etc.

This works fine for small inputs — until it doesn’t.

Senior insight: Most real-world performance incidents I’ve seen trace back to an unnoticed O(n²) loop.

O(2ⁿ) — Exponential Time

This grows faster than reality allows.

Example:

function fibonacci(n: number): number {
  if (n <= 1) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}
  • Or Brute-force solutions , (poorly designed 👀) recursive algorithms, ..etc.

If this shows up in production code, alarms should go off.

A Mental Model for Big O Complexity

Big O complexity is not about exact speed. It’s about how your code behaves as the problem grows.

  • O(1), O(log n) → scalable by design
  • O(n), O(n log n) → acceptable with care
  • O(n²) and beyond → ticking time bombs at scale

A visual summary illustrating how the execution time grows when the input size grows

A visual summary illustrating how the execution time grows when the input size grows

Here’s the trap many engineers fall into:

The dataset is small, so it doesn’t matter.

That statement is temporarily true.

But production systems have a way of:

  • Living longer than expected
  • Being reused in ways you didn’t anticipate
  • Becoming critical infrastructure

As a senior engineer, you don’t optimize prematurely — but you design defensively. Big O is defensive design.

Big O vs Real-World Performance

Reminder on the important truth:

Big O does not measure actual speed.

  • Constants matter
  • Caching matters
  • IO dominates CPU more often than people think

But Big O determines:

  • Whether optimization is possible
  • Whether tuning will help or only delay the inevitable

You can micro-optimize an O(n²) algorithm all you want. It will still lose to a clean O(n log n) solution at scale.

How Senior Engineers Use Big O in Practice

We don’t calculate complexity for every line of code.

We focus on:

  • Hot paths
  • Core loops
  • Data access patterns
  • Code that runs per request, per user, or per record

We ask:

  • “What grows here?”
  • “What happens when this list is 100× bigger?”
  • “Am I looping because it’s easy — or because it’s necessary?”

Big O becomes a thinking tool, not a math exercise.

Big O as a Communication Skill

One underrated aspect of Big O is that it helps you explain trade-offs.

When you say:

This solution is simpler, but it’s O(n²). We’ll feel it later.

You’re not being academic. You’re being responsible.

This shared language helps teams:

  • Make informed decisions
  • Justify refactors
  • Push back on risky shortcuts

Final Thoughts

Big O complexity isn’t something you memorize — it’s something you develop an instinct for over time.

As systems evolve, code rarely runs in isolation. What starts as a simple function often ends up on a critical path, called more frequently, fed with more data, or reused in contexts you didn’t originally plan for. Complexity determines whether that evolution remains manageable or slowly becomes harder to reason about.

Understanding Big O helps you make better everyday decisions, But it also brings clarity to trade-offs. Sometimes a slightly more complex implementation is justified because it keeps future growth predictable. Other times, simplicity wins because the constraints are well understood. Big O gives you a framework to reason about those choices instead of relying on intuition alone.

Senior engineering isn’t about always picking the most optimal algorithm. It’s about being deliberate — knowing the cost of a decision, even when you consciously choose not to optimize.

That awareness is what turns performance from a reactive concern into a design consideration — and it’s a skill that pays off long after the code is written.

Happy coding everyone ✌️


메타데이터
post_id
ecac166527ea
slug
big-o-notation-understanding-complexity-beyond-definitions-ecac166527ea
url
https://medium.com/softwarecraft-mastery/big-o-notation-understanding-complexity-beyond-definitions-ecac166527ea
canonical_url
https://medium.com/softwarecraft-mastery/big-o-notation-understanding-complexity-beyond-definitions-ecac166527ea
author_url
https://medium.com/@saif-hasnaoui
status
ok
fetched_at
2026-06-15 20:49:13