Skip to main content

Design Order Management System - Solution & Explanation

MediumPremiumFree on FleetCodeHash TableDesign17 min readAsked at: Optiver
Practice this problem

Problem Statement

You are asked to design a simple order management system for a trading platform.

Each order is associated with an orderId, an orderType ("buy" or "sell"), and a price.

An order is considered active unless it is canceled.

Implement the OrderManagementSystem class:

  • OrderManagementSystem(): Initializes the order management system.
  • void addOrder(int orderId, string orderType, int price): Adds a new active order with the given attributes. It is guaranteed that orderId is unique.
  • void modifyOrder(int orderId, int newPrice): Modifies the price of an existing order. It is guaranteed that the order exists and is active.
  • void cancelOrder(int orderId): Cancels an existing order. It is guaranteed that the order exists and is active.
  • vector<int> getOrdersAtPrice(string orderType, int price): Returns the orderIds of all active orders that match the given orderType and price. If no such orders exist, return an empty list.

Note: The order of returned orderIds does not matter.

 

Example 1:

Input:
["OrderManagementSystem", "addOrder", "addOrder", "addOrder", "getOrdersAtPrice", "modifyOrder", "modifyOrder", "getOrdersAtPrice", "cancelOrder", "cancelOrder", "getOrdersAtPrice"]
[[], [1, "buy", 1], [2, "buy", 1], [3, "sell", 2], ["buy", 1], [1, 3], [2, 1], ["buy", 1], [3], [2], ["buy", 1]]

Output:
[null, null, null, null, [2, 1], null, null, [2], null, null, []]

Explanation

OrderManagementSystem orderManagementSystem = new OrderManagementSystem();
orderManagementSystem.addOrder(1, "buy", 1); // A buy order with ID 1 is added at price 1.
orderManagementSystem.addOrder(2, "buy", 1); // A buy order with ID 2 is added at price 1.
orderManagementSystem.addOrder(3, "sell", 2); // A sell order with ID 3 is added at price 2.
orderManagementSystem.getOrdersAtPrice("buy", 1); // Both buy orders (IDs 1 and 2) are active at price 1, so the result is [2, 1].
orderManagementSystem.modifyOrder(1, 3); // Order 1 is updated: its price becomes 3.
orderManagementSystem.modifyOrder(2, 1); // Order 2 is updated, but its price remains 1.
orderManagementSystem.getOrdersAtPrice("buy", 1); // Only order 2 is still an active buy order at price 1, so the result is [2].
orderManagementSystem.cancelOrder(3); // The sell order with ID 3 is canceled and removed from active orders.
orderManagementSystem.cancelOrder(2); // The buy order with ID 2 is canceled and removed from active orders.
orderManagementSystem.getOrdersAtPrice("buy", 1); // There are no active buy orders left at price 1, so the result is [].

 

Constraints:

  • 1 <= orderId <= 2000
  • orderId is unique across all orders.
  • orderType is either "buy" or "sell".
  • 1 <= price <= 109
  • The total number of calls to addOrder, modifyOrder, cancelOrder, and getOrdersAtPrice does not exceed 2000.
  • For modifyOrder and cancelOrder, the specified orderId is guaranteed to exist and be active.

Approach Overview

Problem Overview: Design an order management system that supports common operations such as creating orders, retrieving order information, updating status, and possibly canceling or listing orders. The system must handle frequent lookups and updates efficiently, which makes constant‑time access to orders by their ID essential.

Approach 1: Linear List Storage (Brute Force) (Time: O(n), Space: O(n))

The most straightforward design stores all orders in a simple list or array. Each operation scans the list to find the order with a matching identifier. Creating an order is O(1) by appending to the list, but retrieval, updates, or cancellation require iterating through the entire collection. This leads to O(n) time per lookup. The approach works for small datasets but quickly becomes inefficient when the number of orders grows.

Approach 2: Hash Table Index by Order ID (Time: O(1), Space: O(n))

A more practical design uses a hash table keyed by orderId. Each order is stored as a value object containing details such as status, items, or timestamps. When an operation arrives, the system performs a constant‑time hash lookup to retrieve the corresponding order. Updates simply modify the stored object, while deletions remove the key from the table. This structure makes create, read, update, and delete operations all O(1) on average, which is exactly what high‑throughput backend systems need.

Approach 3: Hash Table with Secondary Indexes (Time: O(1) average, Space: O(n))

If the system must support queries such as retrieving all orders for a user or filtering by status, a single map by order ID is not enough. The design can be extended with multiple hash tables: one mapping orderId → order, and additional indexes like userId → list of orderIds or status → set of orders. Each write operation updates all relevant indexes. Reads remain fast because the system jumps directly to the required set using a hash lookup. This pattern appears frequently in system design problems where multiple access paths are required.

Recommended for interviews: Interviewers expect the hash table design. The brute force list demonstrates baseline reasoning but fails to meet scalability expectations. A primary hash map keyed by order ID gives O(1) average complexity for core operations and reflects how real backend services implement order storage. Adding secondary indexes shows strong design thinking when the problem includes additional query requirements.

Solution

We use a hash table orders to store the type and price information of each order, where the key is the order ID and the value is a tuple (orderType, price). Additionally, we use another hash table t to store the list of order IDs corresponding to each (orderType, price), where the key is a tuple (orderType, price) and the value is the list of order IDs.

When calling \texttt{addOrder}, we add the order information to orders and append the order ID to the corresponding list in t.

When calling \texttt{modifyOrder}, we first retrieve the order type and old price from orders, then update the order's price information. Next, we remove the order ID from the corresponding list in t and add it to the list corresponding to the new price.

When calling \texttt{cancelOrder}, we retrieve the order type and price information from orders, then remove the order ID from the corresponding list in t and delete the order from orders.

When calling \texttt{getOrdersAtPrice}, we directly return the list of order IDs corresponding to the query in t.

In the above operations, the time complexity for adding and retrieving the order ID list is O(1), while the time complexity for removing an order ID from the list is O(n), where n is the length of the corresponding list. Since the total number of orders in the problem does not exceed 2000, this method is efficient enough in practice. The space complexity is O(m), where m is the total number of orders.

Code

Python

Java

C++

Go

TypeScript

Rust

Try this approach in the editor →

Detailed Complexity Analysis

ApproachTimeSpaceWhen to Use
Linear List StorageO(n) lookupO(n)Small datasets or initial brute‑force prototype
Hash Table by Order IDO(1) averageO(n)General case with frequent order lookups and updates
Hash Table with Secondary IndexesO(1) averageO(n)When queries require filtering by user, status, or other attributes

Video Solution

Design Order Management System • Owen Wu • 46 views views

Frequently Asked Questions

Is Design Order Management System easy or hard?
Design Order Management System is typically considered a medium difficulty problem. The core implementation with a hash map is straightforward, but interviewers often expect clean class design and efficient handling of updates and queries.
Design Order Management System Python/Java solution
In Python, a dictionary can map orderId to an Order object, giving O(1) average lookup. In Java, HashMap<Integer, Order> is commonly used. Both implementations follow the same pattern: store orders by ID and update or retrieve them with direct hash lookups.
How to solve Design Order Management System in O(n)?
A simple implementation stores all orders in a list and iterates through it to locate the required order. Each search or update scans the entire collection, giving O(n) time per operation. This approach is easy to implement but does not scale well compared to the O(1) hash table solution.
What is the best approach for Design Order Management System?
The most effective approach uses a hash table keyed by order ID. This allows constant-time O(1) average operations for creating, retrieving, updating, and deleting orders. The design mirrors how real backend services store transactional objects where fast lookups are critical.
Is Design Order Management System asked at Google/Amazon/Meta?
Design-style data structure problems using hash tables appear frequently in interviews at companies like Amazon, Google, and Meta. Variations of order tracking, task management, or object registries test the candidate's ability to combine hash maps with clean system design.
What data structure is used in Design Order Management System?
The core data structure is a hash table (hash map) that maps order IDs to order objects. Some implementations also maintain additional maps such as user-to-orders or status-to-orders to support efficient queries.
What is the time complexity of Design Order Management System?
Using a hash table, most operations such as create, get, update, and delete run in O(1) average time. Space complexity is O(n) because each order must be stored in memory. A naive list-based design would require O(n) lookup time.

Ready to solve this problem?

Practice Design Order Management System with our built-in code editor and test cases.

Practice on FleetCode