Skip to content

Order Capacity Management

Overview

Order Capacity Management controls how many orders and items your kitchen can handle per time slot. This prevents kitchen overload by limiting orders during busy periods.

Key Purpose: Ensure kitchen can fulfill all orders on time by limiting incoming orders based on capacity.

Purpose

This page lets you configure order and item limits per time slot so your kitchen is never overwhelmed, with support for rush protection, category-specific caps, and time-specific rules.

Key Concepts

  • Time Slot: A fixed-duration window (e.g., 15 or 30 minutes) used to group orders for capacity counting. Orders are assigned to a slot based on their order_prep_time, which is the requested time minus preparation time.
  • Rush Protection: A flexible limit system that allows extra low-value orders when the slot's total order value is below a configured threshold, preventing one large order from blocking the entire slot.
  • Category-Specific Limits: Independent item caps per menu category (e.g., max 6 pizzas per slot for oven capacity), checked alongside global order and item limits.
  • Time-Specific Rules: Override rules that apply different capacity limits during specific days and time ranges (e.g., reduced limits during lunch rush), with null fields inheriting from base settings.
  • Clamp Behavior: During time-specific windows, rush protection's allow_up_to value is automatically clamped to never exceed the time-specific order cap, ensuring time-specific rules are always the hard ceiling.

Actions

Enable/Disable Capacity Management

Toggle the master capacity switch. When disabled, all capacity checks are fully bypassed and all time slots within business hours are shown as available regardless of configured limits.

Configure Order and Item Limits

Set the maximum number of orders and/or total items allowed per time slot. Both limits are checked simultaneously and an order is rejected if any limit would be exceeded.

Set Up Rush Protection

Enable flexible ordering to allow extra low-value orders when a slot's total value is below the threshold. Configure the expanded order limit (allow_up_to) and the value threshold.

Add Time-Specific Rules

Create named rules that override default limits during specific days and time ranges (e.g., "Lunch Rush" Mon-Fri 12:00-13:30 with reduced order cap). Empty fields inherit from base settings.

Configure Category Limits

Set per-category item caps for slow-prep categories like pizzas or grilled items, ensuring equipment-constrained items do not bottleneck the kitchen.

Location

  • Backoffice Route: /online-settings
  • Applies to: Online Ordering (Pickup & Delivery) only
  • Does NOT apply to: In-House / QR Ordering, Kiosk
  • Backend Service: app/Services/OrderCapacity/OrderCapacityService.php
  • Vue Component: src/views/in-house/components/forms/OrderCapacityManagement.vue
  • Translations: src/plugins/i18n/locales/modules/{lang}/online-settings.ts

Fields

Capacity Enabled (Master Toggle)

PropertyValue
Field IDenabled
LabelEnable Order Capacity Management
TypeToggle (Boolean)
Defaultfalse
RequiredNo

Description: Master toggle to enable or disable all order capacity management.

Business Logic:

  • When enabled=false: Hard bypass - all capacity checks are skipped
  • All time slots show as available regardless of configured limits
  • Stale configuration values are ignored (prevents accidental enforcement)
  • API response includes capacity_disabled: true flag for debugging

Customer Impact:

  • Online Ordering: All time slots within business hours are available for selection

Why this matters: Prevents the scenario where a merchant disables capacity management but old configured values accidentally block orders.


Time Slot Duration

PropertyValue
Field IDtime_slot_duration_min
LabelTime Slot Duration
TypeSelect
Options5, 10, 15, 20, 30, 45, 60 minutes
Default30
RequiredYes
ValidationMust be one of the allowed values

Description: The length of each time slot for capacity calculations. Orders are grouped into these time windows for capacity checking.

Business Logic:

  • Orders are grouped into time slots of this duration
  • Capacity limits are checked per slot
  • Shorter slots = more precise control but harder to manage
  • Longer slots = simpler but less granular control

Customer Impact:

  • Online Ordering: Customers see available pickup/delivery times rounded to these intervals. With 15-minute slots, times show as 12:00, 12:15, 12:30, etc.

Examples:

  • Fast food (high volume, quick prep): 15 minutes
  • Standard restaurant: 30 minutes
  • Catering/complex orders: 60 minutes

Limit Orders Per Time Slot (Toggle)

PropertyValue
Field IDlimit_orders_per_time_slot
LabelLimit number of orders per time slot
TypeToggle (Boolean)
Defaultfalse
RequiredNo

Description: Enable to set a maximum number of orders that can be placed in each time slot.

Business Logic:

  • When enabled, system counts orders per time slot
  • New orders blocked when count >= limit
  • Counts both paid and pending orders

Customer Impact:

  • Online Ordering: When a time slot reaches its order limit, customers cannot select that time. They see the next available slot.

Related Fields: number_of_orders_per_time_slot


Number of Orders Per Time Slot

PropertyValue
Field IDnumber_of_orders_per_time_slot
LabelMaximum orders per time slot
TypeNumber
Default10
RequiredYes (when toggle enabled)
Validationmin: 1
Depends Onlimit_orders_per_time_slot must be true

Description: The maximum number of orders allowed in each time slot.

Business Logic:

  • System counts all orders with order_prep_time in the slot
  • Includes paid orders and pending payment orders
  • New orders blocked when count >= this limit

Customer Impact:

  • Online Ordering: If set to 5, only 5 customers can order for the 12:00-12:15 slot. The 6th customer sees "Time slot unavailable" and must choose another time.

Examples:

  • Small kitchen: 3-5 orders per slot
  • Medium kitchen: 8-12 orders per slot
  • Large kitchen: 15-25 orders per slot

Troubleshooting:

  • If customers report no available times → limit may be too low
  • Check transaction history to see actual order volume per slot
  • Consider increasing during slow periods, decreasing during rush hours

Protect Rush Capacity (Rush Protection)

Currency note: All monetary examples in this section use numbers only. The actual currency depends on your store configuration (€, $, etc.).

PropertyValue
Field IDenable_flexible_limit_order_per_time_slot
LabelProtect rush capacity
TypeToggle (Boolean)
Defaultfalse
RequiredNo
Depends Onlimit_orders_per_time_slot must be true AND number_of_orders_per_time_slot > 0

Description: Allow extra low-value orders when the slot's total value is still low. Prevents one large order from blocking your entire rush capacity.

UI Behavior (Configure → Summary pattern):

  • Toggle ON + fields empty → shows input fields with hint "Configure how many extra orders to allow and the value threshold"
  • Toggle ON + fields configured → shows summary: "Accept up to X extra orders, as long as slot total stays under [configured amount]" with Edit button
  • Fields use placeholders instead of pre-filled defaults

Business Logic:

  • If timeslot total value < threshold → allow up to allow_up_to orders
  • Otherwise → use standard number_of_orders_per_time_slot limit
  • Clamp behavior: During time-specific windows, allow_up_to is automatically clamped to never exceed the time-specific order cap. This ensures time-specific rules are always the hard cap.
  • Note: Rush protection never increases capacity beyond the highest order limit currently in effect (default or time-specific).

Customer Impact:

  • Online Ordering: Small orders (like just drinks) may still be accepted even when the slot would otherwise be "full" for larger orders.

Merchant Explanation: "Rush protection lets you accept a few extra low-value orders, as long as the total value of the time slot stays manageable for your kitchen."

Related Fields: allow_up_to, value_threshold_per_time_slot


Rush Protection: Allow Up To

PropertyValue
Field IDallow_up_to
LabelAllow up to X extra orders
TypeNumber
Defaultnull (empty with placeholder "5")
RequiredYes (when rush protection enabled)
Validationmin: 1, should be > number_of_orders_per_time_slot
Depends Onenable_flexible_limit_order_per_time_slot must be true

Description: Maximum orders allowed when the time slot's total value is below the threshold.

Business Logic:

  • This is the "expanded" limit for low-value slots
  • Clamp: During time-specific windows, this value is automatically reduced to match the time-specific order cap if it would exceed it
  • Example: Base allow_up_to=5, time-specific cap=2 → effective allow_up_to=2 during that window

Rush Protection: Value Threshold

PropertyValue
Field IDvalue_threshold_per_time_slot
LabelSlot total threshold
TypeCurrency
Defaultnull (empty with placeholder showing example amount)
RequiredYes (when rush protection enabled)
Validationmin: 0
Depends Onenable_flexible_limit_order_per_time_slot must be true

Description: If the total order value in a time slot is below this amount, the rush protection limit (allow_up_to) applies instead of the standard limit.

Note: The value threshold always uses your store's configured currency (€, $, or any supported currency). No conversion is applied.

Business Logic:

  • Sum of all order totals in slot compared to this threshold
  • If sum < threshold → use allow_up_to limit
  • If sum >= threshold → use number_of_orders_per_time_slot limit

Examples (amounts in your store's currency):

  • Set to 45: If slot has 30 in orders, rush protection allows extra orders
  • Set to 100: More room for small orders before standard limit kicks in

Merchant Explanation: "Accept up to [X] extra orders, as long as the slot total stays under [your configured amount]."


Limit Items Per Time Slot (Toggle)

PropertyValue
Field IDlimit_items_per_time_slot
LabelLimit total items per time slot
TypeToggle (Boolean)
Defaultfalse
RequiredNo

Description: Enable to set a maximum number of items (across all orders) that can be processed in each time slot.

Business Logic:

  • Counts total quantity of all items in all orders for the slot
  • More granular than order count
  • Prevents kitchen overload from large orders

Customer Impact:

  • Online Ordering: A single order with 20 items counts as 20 toward the limit. Large orders may be rejected or pushed to later slots.

Related Fields: number_of_items_per_time_slot


Number of Items Per Time Slot

PropertyValue
Field IDnumber_of_items_per_time_slot
LabelMaximum items per time slot
TypeNumber
RequiredYes (when toggle enabled)
Validationmin: 1
Depends Onlimit_items_per_time_slot must be true

Description: The maximum total number of items allowed across all orders in each time slot.

Business Logic:

  • Each item in an order counts toward this limit
  • Modifiers do NOT count separately
  • Quantity matters: 3x Pizza = 3 items

Examples:

  • If limit is 15: Order A (5 items) + Order B (8 items) = 13 items
  • Order C (3 items) would be rejected (13+3=16 > 15)

Enable Category-Specific Limits

PropertyValue
Field IDenable_limit_specific_categories
LabelSet limits for specific item categories
TypeToggle (Boolean)
Defaultfalse
RequiredNo

Description: Enable to set different capacity limits for specific menu categories. Useful when some items take longer to prepare.

Business Logic:

  • Each category can have its own item limit per slot
  • All category limits are checked independently
  • An order is rejected if ANY category limit would be exceeded

Customer Impact:

  • Online Ordering: If pizza limit is reached but burger limit is not, customer can still order burgers but not pizzas.

Related Fields: limit_specific_categories


Category-Specific Limits

PropertyValue
Field IDlimit_specific_categories
LabelCategory limits
TypeArray of objects
RequiredNo
Depends Onenable_limit_specific_categories must be true

Item Schema:

json
{
  "category_id": "string (MongoDB ObjectId)",
  "category_name": "string",
  "number_of_items_per_time_slot": "number (min: 1)"
}

Description: Define maximum items per time slot for specific categories.

Business Logic:

  • For each category, count items in that category across all orders in the slot
  • Each category limit is checked independently
  • Order rejected if any category limit exceeded

Examples:

  • Pizzas: 5 per slot (oven capacity)
  • Fries: 10 per slot (fryer capacity)
  • Drinks: 20 per slot (easy to prepare)

Time-Specific Rules

PropertyValue
Field IDtime_specific_rules
LabelTime-specific capacity rules
TypeArray of objects
RequiredNo

Item Schema:

json
{
  "name": "string (e.g., 'Lunch Rush')",
  "time_range": {
    "from": "string (HH:mm)",
    "to": "string (HH:mm)"
  },
  "active_days": ["Monday", "Tuesday", ...],
  "number_of_orders_per_time_slot": "number",
  "number_of_items_per_time_slot": "number (optional)",
  "limit_specific_categories": [
    {
      "category_id": "string",
      "category_name": "string",
      "number_of_items_per_time_slot": "number"
    }
  ]
}

Description: Override default capacity settings during specific time periods. Perfect for managing rush hours.

UI Behavior:

  • Time-specific rules only show order/item limit overrides (simplified UI)
  • "Leave empty to use default": If a field is left empty (null), the base default value is used
  • Category limits and rush protection are always inherited from base settings

Business Logic:

  • Rules are checked by day and time
  • If current time matches a rule, that rule's limits are merged with base settings:
    • If time-specific value is set (>0) → override base
    • If time-specific value is null/empty → inherit from base
    • Rush protection always inherited from base (clamped to time-specific cap)
    • Category limits always inherited from base
  • Multiple rules can exist; first matching rule applies

Clamp Behavior:

  • During time-specific windows, rush protection allow_up_to is automatically clamped to never exceed the time-specific order cap
  • Example: Base allow_up_to=5, time-specific cap=2 → effective limit is 2 (not 5)
  • Merchant explanation: "Rush protection can help within a time-specific window, but it will never exceed the rush-hour limit you set."

Examples:

  • Lunch Rush (11:30-13:30, Mon-Fri): Reduce to 3 orders/slot
  • Weekend Dinner (18:00-21:00, Sat-Sun): Reduce to 5 orders/slot
  • Happy Hour (16:00-18:00, Mon-Thu): Increase drinks category to 30/slot

Business Logic

How Limits Work Together

All enabled limits are checked simultaneously. An order is rejected if ANY limit would be exceeded.

Enforcement Order:

  1. Check if order count limit would be exceeded
  2. Check if total items limit would be exceeded
  3. Check if any category-specific limit would be exceeded
  4. If time-specific rule applies, use those limits instead of defaults
  5. If flexible ordering enabled and slot value < threshold, use flexible limit

Time Slot Calculation

How the system determines which time slot an order belongs to:

  1. Take the order's requested pickup/delivery time
  2. Subtract preparation time to get order_prep_time
  3. Round order_prep_time down to nearest slot boundary
  4. That slot is where the order's capacity is counted

Example:

  • Customer requests pickup at 12:45
  • Preparation time is 20 minutes
  • order_prep_time = 12:25
  • With 15-minute slots, order counts toward 12:15-12:30 slot

Split Order Handling

When an order is too large for one slot, it can be split across multiple slots:

  1. Calculate how many items can fit in current slot
  2. If not all items fit, check next available slot
  3. Continue until all items are allocated
  4. Order is assigned to first slot, but capacity counted in all slots

Backend Implementation

Key methods in OrderCapacityService.php:

  • checkOrderCapacity() - Validates if order can be placed
  • getOrderCapacity() - Gets capacity settings for location
  • getSentAt() - Calculates when order should be sent to kitchen
  • calculateSplitTimeslots() - Handles large orders across slots
  • getTimeslotAvailableCapacity() - Checks remaining capacity
  • isWithinBusinessHours() - Validates against business hours

Customer Impact

Online Ordering

  • Customers see only available time slots
  • Full slots are hidden from selection
  • If no slots available, message shows "No delivery/pickup times available"
  • Large orders may show later times if current slots are near capacity
  • Time slots respect business hours

KDS (Kitchen Display System)

  • Kitchen sees orders grouped by time slot
  • Helps staff prepare for upcoming rush periods
  • Orders appear with their scheduled time

Relations

Depends On

  • Business Hours: Capacity only applies within business hours
  • Locations: Each location has its own capacity settings
  • Menu Categories: Category limits reference menu categories

Affects

  • Online Ordering: Determines available time slots for pickup/delivery
  • Transactions: Orders tagged with time slot info

Business Rules

  • Order capacity only applies to online ordering (pickup and delivery); it does not affect kiosk orders, in-house/QR orders, or POS orders. Kiosk and online ordering dine-in ("ForHere") orders bypass capacity checks entirely.
  • When capacity management is disabled (enabled=false), all configured limits are fully bypassed -- stale configuration values are ignored and no capacity checks are applied.
  • All enabled limits (order count, item count, category-specific) are checked simultaneously; an order is rejected if any single limit would be exceeded.
  • The system uses database-level locking with retry logic when updating transaction capacity data to prevent race conditions during concurrent order placement.
  • After a transaction is assigned to a time slot, the cache for that slot is immediately cleared to prevent stale reads from allowing over-capacity orders.

FAQs

  • Does order capacity affect kiosk or POS orders? No. Capacity management only applies to online ordering (pickup and delivery). Kiosk, QR ordering, and POS orders are not subject to capacity limits.
  • What happens when I disable capacity management? All limits are fully bypassed immediately. Old configured values are ignored and all time slots within business hours become available. The API response includes a capacity_disabled flag for debugging.
  • How does the system handle concurrent orders? The backend uses database-level locking with retry logic to prevent two orders from being assigned to the same slot when it is at capacity. If lock acquisition fails after retries, the customer sees a "try again in a moment" message.
  • Can a large order be split across multiple time slots? Yes. When an order is too large for one slot, the system calculates how many items fit in the current slot and allocates the remainder to subsequent slots. The order is assigned to the first slot but capacity is counted across all affected slots.
  • What is the difference between time-specific rules and rush protection? Time-specific rules set hard limits for specific days and time ranges. Rush protection allows extra low-value orders within those limits when the slot value is still low. Time-specific rules always take priority and rush protection can never exceed a time-specific cap.

Troubleshooting

Problem: Customers report no available time slots

Possible Causes:

  • Order limits set too low for actual demand
  • Time-specific rule reducing capacity during peak hours
  • Business hours not configured correctly
  • All slots filled with existing orders

Solutions:

  1. Check current order volume in Transactions
  2. Temporarily increase limits during testing
  3. Review time-specific rules for conflicts
  4. Verify business hours include expected ordering times
  5. Check if there's a backlog of pending orders

Problem: Kitchen is overwhelmed despite capacity limits

Possible Causes:

  • Limits set too high
  • Category limits not configured for slow-prep items
  • Time slot duration too long
  • Large orders not being split properly

Solutions:

  1. Reduce orders per slot limit
  2. Add category-specific limits for complex items (pizzas, grilled items)
  3. Use shorter time slots (15 min instead of 30)
  4. Add time-specific rules for rush hours
  5. Review item preparation times

Problem: Orders being rejected unexpectedly

Possible Causes:

  • Multiple limits active and one is being hit
  • Time-specific rule with stricter limits
  • Category limit reached for specific item
  • Pending orders counting toward capacity

Solutions:

  1. Check which limit is being hit in order logs
  2. Review all active limits and time-specific rules
  3. Consider if all limits are necessary
  4. Check for stuck pending orders

Examples

Small Pizza Shop

json
{
  "time_slot_duration_min": 15,
  "limit_orders_per_time_slot": true,
  "number_of_orders_per_time_slot": 4,
  "limit_items_per_time_slot": false,
  "enable_limit_specific_categories": true,
  "limit_specific_categories": [
    {
      "category_name": "Pizzas",
      "number_of_items_per_time_slot": 6
    }
  ]
}

Explanation: Max 4 orders per 15 minutes, but never more than 6 pizzas. This accounts for oven capacity (typically 2-3 pizzas at a time, ~5 min each).


Busy Lunch Restaurant

json
{
  "time_slot_duration_min": 30,
  "limit_orders_per_time_slot": true,
  "number_of_orders_per_time_slot": 15,
  "time_specific_rules": [
    {
      "name": "Lunch Rush",
      "time_range": { "from": "12:00", "to": "13:30" },
      "active_days": ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday"],
      "number_of_orders_per_time_slot": 8
    }
  ]
}

Explanation: Normal capacity is 15 orders/slot, but during lunch rush it drops to 8 to maintain quality and prevent delays.


Coffee Shop with Flexible Ordering

json
{
  "time_slot_duration_min": 15,
  "limit_orders_per_time_slot": true,
  "number_of_orders_per_time_slot": 10,
  "enable_flexible_limit_order_per_time_slot": true,
  "allow_up_to": 15,
  "value_threshold_per_time_slot": 50
}

Explanation: Normally max 10 orders per slot. But if the slot's total value is under 50 (in your store's currency, e.g. €50 or $50), allow up to 15 orders. This maximizes throughput for quick drinks while protecting against too many complex food orders.


Common Merchant Questions

1. "Why are orders still coming in even though I set a limit?"

Order capacity only applies to online ordering (pickup & delivery). It does not affect in-house orders, QR ordering, kiosk, or POS orders.


2. "I turned order capacity off — are my old limits still active?"

No. When order capacity is disabled, all limits are fully bypassed. Old values are ignored and no capacity checks are applied.


3. "What's the difference between a time-specific rule and rush protection?"

  • Time-specific rules set hard limits for specific days and times (e.g. Friday 18:00–20:00).
  • Rush protection allows a few extra low-value orders within those limits when the kitchen can still handle them.

4. "Which one wins if they overlap?"

Time-specific rules always win. Rush protection can never exceed the limit set by a time-specific rule.


5. "If I leave a field empty, what happens?"

Empty fields mean "use the default setting", not zero. Limits are only enforced when a value is explicitly set.


6. "Why does rush protection use a value threshold instead of item count?"

Because value is a good proxy for kitchen workload. Many small, low-value orders are often faster to prepare than a few large, complex ones. The threshold is always evaluated in your store's currency.


7. "Does rush protection apply all the time?"

No. It only applies:

  • When enabled
  • When properly configured
  • And only within the active order capacity limits

8. "Can rush protection increase my limits during busy hours?"

No. Rush protection can help during quieter moments, but it never increases limits during busy or restricted time windows.


9. "Why do I see time slots available even when capacity is off?"

When capacity is disabled, all available business hours are shown as open. This is expected behavior.


10. "What happens if I set limits that are too strict?"

If a time slot is full, customers will be asked to choose a later time — or confirm a delayed order if enabled.


11. "Is the value threshold per order or per time slot?"

It's per time slot, not per order. The total value of all orders in the slot is evaluated together.


12. "Does this affect POS / phone orders?"

No. Order capacity only affects online orders placed through your ordering website or app. Orders entered directly in the POS are not blocked.


13. "Why does a time slot disappear instead of showing 'full'?"

Full time slots are hidden to guide customers toward available times and avoid failed checkouts. This reduces frustration and abandoned orders.


14. "What happens if my preparation time changes?"

Capacity is calculated using preparation time. If you increase prep time, orders may shift into earlier time slots for capacity counting. This can affect availability during busy periods.


15. "Why does a small order get accepted when a larger one is rejected?"

Because rush protection allows extra low-value orders when the slot total is still under the threshold. Larger orders push the slot value over the threshold faster.


16. "Can I use rush protection without limiting orders per slot?"

No. Rush protection only works on top of an order limit. It adjusts how the limit behaves; it does not replace it.