Ring Buffer (Circular Buffer)

A fixed-size array used as a circular queue with O(1) enqueue and dequeue by wrapping indices, avoiding memory allocation after initialization.

Syntax

class RingBuffer {
  constructor(capacity) {
    this.buf = new Array(capacity);
    this.head = 0; this.tail = 0; this.size = 0;
  }
  enqueue(val) { ... }  // O(1)
  dequeue()    { ... }  // O(1)
}

Parameters

NameTypeRequiredDescription
capacity number Yes Maximum number of elements the buffer can hold at once.

Returns

RingBuffer — A new fixed-capacity ring buffer.

Throws

  • Error — Overflow when enqueue is called on a full buffer (or element is dropped, depending on policy).

Examples

class RingBuffer {
  #buf; #cap; #head = 0; #tail = 0; #size = 0;
  constructor(cap) { this.#cap = cap; this.#buf = new Array(cap); }
  get size() { return this.#size; }
  isFull()  { return this.#size === this.#cap; }
  isEmpty() { return this.#size === 0; }
  enqueue(val) {
    if (this.isFull()) throw new Error('Buffer overflow');
    this.#buf[this.#tail] = val;
    this.#tail = (this.#tail + 1) % this.#cap;
    this.#size++;
  }
  dequeue() {
    if (this.isEmpty()) return undefined;
    const val = this.#buf[this.#head];
    this.#head = (this.#head + 1) % this.#cap;
    this.#size--;
    return val;
  }
  peek() { return this.isEmpty() ? undefined : this.#buf[this.#head]; }
}

const rb = new RingBuffer(3);
rb.enqueue(1); rb.enqueue(2); rb.enqueue(3);
console.log(rb.dequeue(), rb.dequeue());
rb.enqueue(4);
console.log(rb.peek(), rb.size);
Output
1 2
3 2
// Sliding window log: keep last N log entries
const log = new RingBuffer(5);
for (let i = 1; i <= 8; i++) {
  if (log.isFull()) log.dequeue(); // drop oldest
  log.enqueue(`event-${i}`);
}
const entries = [];
while (!log.isEmpty()) entries.push(log.dequeue());
console.log(entries);
Output
[ 'event-4', 'event-5', 'event-6', 'event-7', 'event-8' ]

Notes

| Operation | Time | Space | |----------|------|--------------| | Enqueue | O(1) | O(1) | | Dequeue | O(1) | O(1) | | Peek | O(1) | O(1) | | Total | — | O(capacity) | Ring buffers are preferred in real-time and embedded systems where heap allocation must be avoided (audio buffers, network I/O queues). The modulo (`%`) wraps indices without any data movement. Can be backed by a power-of-2 capacity to replace `%` with a bitwise AND: `(i + 1) & (cap - 1)`.

See also