Module F-7·14 min read

FIFO structure, circular queues, and the queueing patterns behind message brokers and job schedulers.

JJS
Written by Jatin Jain Saraf · Senior Software Engineer

Module F-7 — Queues: FIFO, Circular Queues, and Job Scheduling

What this module covers: Where a stack processes the most recent item first, a queue processes the oldest item first — first in, first out. This module covers the queue as an abstract data type, why the obvious array-based implementation is quietly O(n) per operation, the circular buffer that fixes it, and why message brokers and job schedulers are built on queues rather than stacks.


The Queue: First-In, First-Out

A queue supports enqueue (add to the back) and dequeue (remove from the front) — the exact opposite access pattern from a stack. Whatever was added first is the first thing that comes back out.

typescript

Analogy: A queue is a line at a counter. New arrivals join at the back; whoever has been waiting longest is served next, from the front. Nobody gets served out of order just because they're standing closer to the front of the physical line by accident — position in the queue is exactly the order of arrival.


The Naive Implementation's Hidden Cost

The obvious approach — a plain array, push() to enqueue, shift() to dequeue — looks correct and is correct. It's also quietly expensive:

typescript

This is the exact insertion/deletion cost distinction from Module F-2: push() is O(1) because it only touches the end, but shift() is O(n) because every remaining element has to move one position to the left to stay contiguous. A queue implemented this way is O(n) per dequeue — fine for a handful of items, a measurable bottleneck once a queue is processing thousands of jobs.


Fixing It: Two Pointers Instead of Physical Shifting

The fix doesn't require a different memory layout — it requires not physically moving elements at all. Instead of shifting everything left after a dequeue, just move a pointer forward to mark "everything before here has already been removed":

typescript

Both enqueue and dequeue are now genuinely O(1) — no element is ever physically moved. The cost of this approach is that head and tail grow forever in an unbounded queue; in practice, this is fine for most application code (the numbers are just array/object indices, and modern runtimes handle large integers without issue), but a fixed-capacity version needs one more idea: wrapping around.


The Circular Queue

A circular queue uses a fixed-size backing array and wraps head/tail back to the start using the modulo operator once they reach the end — reusing freed-up slots instead of growing forever.

typescript

Sign in to keep reading

The rest of this module is free — sign in with Google to unlock it and track your progress.

Sign in & Register

Discussion

0

Join the discussion

Loading comments...

© 2026 Jatin Jain Saraf (JJS). All rights reserved.