How do you design a circular queue with a fixed capacity, and what is the tricky part?
Use a fixed size array and a head index that wraps around. The wrap is what the modulo does: the next write position is the head plus the number of items currently stored, taken modulo the capacity. Because the array is circular, the space freed at the front becomes available at the back again, so you never need to shift elements.
The genuinely tricky part is telling an empty queue from a full one. If you only track a head index, the queue looks empty when head equals the write position, which happens both when it is empty and when it is completely full. The standard solutions are to keep a separate count, which is the simplest, or to sacrifice one slot so that the head and the write position can never coincide in both states.
The mechanism is that the array is treated as a ring. Index arithmetic is always taken modulo the capacity, so position n minus one is followed by position zero. The write position is derived from the head and the count, so it always points at the first free slot.
The trade-off to name is the one-slot sacrifice. Reserving a slot avoids the extra counter and the branch that maintains it, at the cost of being able to hold one fewer element than the array size. That is a constant factor, so it rarely matters, but it changes the capacity semantics and interviewers sometimes care about it. The other design question is thread safety: a queue shared between a producer and a consumer needs locking or a lock-free ring buffer, and the lock-free version relies on careful memory ordering that is genuinely difficult to get right.