The Duplicate Order Bug That Should Have Never Happened

I am a full-stack developer (currently working with cognizant) who is passionate about web development and creating digital products with innovative solutions.
I hold 6+ years of experience in development, understanding clients' unique needs, and delivering quality code. I've honed my coding skills over these years through both my professional exposure and self-study. Have worked with teams that have used agile development methodology.
I am someone who likes to keep acquiring new skills and capabilities. And when I am not a web developer, I enjoy reading, writing and running.
My interests include:
- Exploring new ideas
- Learning about future tech & products
- Finding user-friendly solutions to tech-related problems
- Sharing my knowledge with close acquaintances
A checkout bug once slipped into production.
A customer placed an order with three items.
But the order record showed the same product twice.
Not two quantities.
Two rows.
The UI didn’t show it clearly.
The backend didn’t block it.
The payment logic didn’t complain.
But the warehouse system did.
Two shipping labels were generated for the same item.
The root cause wasn’t a broken API.
It wasn’t a race condition.
It was a missing composite primary key.
The database had no rule preventing a product from appearing twice in the same order.
That day reinforced a lesson every backend engineer eventually learns:
If a relationship should be unique, the database must enforce it.
In this guide, we are going to explore one critical relational modeling concept:
- Composite Primary Keys
And more importantly, when they matter in real production systems.
1️⃣ Composite Primary Keys: When One Column Isn’t Enough
A composite primary key is a primary key made from multiple columns combined together.
Instead of a single-column identifier like:
PRIMARY KEY (id)
You define uniqueness using a combination of values:
PRIMARY KEY (column1, column2)
Neither column alone is unique.
But the combination must always be unique.
The Attendance Sheet Analogy
Imagine a classroom attendance system.
If you store attendance records like this:
| student_id | date |
|---|---|
| 101 | 2024-01-01 |
Is student_id unique?
No — students attend many days.
Is date unique?
No — many students attend on the same day.
But the combination:
(student_id + date)
is unique.
That pair identifies one attendance record.
That’s exactly what composite keys represent.
2️⃣ Why Composite Keys Exist in Real Systems
In real applications, not every table represents a standalone entity.
Some tables represent relationships between entities.
These appear in:
Many-to-many relationships
Mapping tables
Enrollment systems
Tagging systems
Access control tables
In those tables, uniqueness is defined by multiple columns together.
🛒 Real Industry Example: E-Commerce Order Items
Let’s walk through a classic scenario.
You’re building an e-commerce platform.
Business rules:
A user places orders.
An order can contain many products.
A product can appear in many orders.
A product should not appear twice in the same order.
This is a many-to-many relationship.
To model it, we create an intermediate table.
🧩 Designing the order_items Table
CREATE TABLE order_items (
order_id INT NOT NULL,
product_id INT NOT NULL,
quantity INT NOT NULL,
price DECIMAL(10,2) NOT NULL,
PRIMARY KEY (order_id, product_id)
);
This table connects:
ordersproducts
And enforces one important rule:
A product cannot appear twice within the same order.
What the Composite Key Enforces
The pair:
(order_id, product_id)
must be unique.
So this is invalid:
| order_id | product_id | quantity |
|---|---|---|
| 101 | 55 | 2 |
| 101 | 55 | 1 |
But this is valid:
| order_id | product_id |
|---|---|
| 101 | 55 |
| 101 | 56 |
Because the combinations differ.
What Each Column Represents
| Column | Purpose |
|---|---|
| order_id | Reference to the order |
| product_id | Reference to the product |
| quantity | Number of items purchased |
| price | Price snapshot at purchase |
Notice something important:
There is no extra ID column.
Because the relationship itself defines identity.
3️⃣ What Happens Without Composite Keys
Let’s imagine the table without this constraint.
CREATE TABLE order_items (
id INT AUTO_INCREMENT PRIMARY KEY,
order_id INT,
product_id INT
);
Now nothing stops this:
| id | order_id | product_id |
|---|---|---|
| 1 | 101 | 55 |
| 2 | 101 | 55 |
Duplicate relationships.
These duplicates create problems in:
billing
shipping
analytics
inventory
Eventually someone writes a deduplication script.
Which means the database is fixing problems it should have prevented.
4️⃣ Composite Keys and Index Behavior
A composite primary key automatically creates a composite index.
But composite indexes have an important rule:
They are ordered left to right.
Example:
PRIMARY KEY (order_id, product_id)
The index order is:
(order_id → product_id)
This means queries filtering by order_id are efficient.
Example:
SELECT * FROM order_items
WHERE order_id = 101;
But filtering only by product_id is less efficient.
Example:
SELECT * FROM order_items
WHERE product_id = 55;
In that case, we add an additional index.
CREATE INDEX idx_product_id ON order_items(product_id);
Understanding index order is critical for query performance.
5️⃣ Composite Keys vs Surrogate IDs
Some systems prefer this design:
id INT AUTO_INCREMENT PRIMARY KEY,
UNIQUE (order_id, product_id)
This approach introduces a surrogate key.
Both designs enforce uniqueness.
But they reflect different architectural preferences.
When Composite Keys Are Better
Use composite keys when:
The uniqueness rule naturally involves multiple columns
The table represents a relationship
There is no meaningful single identifier
Examples:
enrollment tables
tag mappings
order item tables
role assignments
When Surrogate Keys Are Better
Use a single-column primary key when:
External systems reference the row
ORMs expect a simple identifier
The record has an independent lifecycle
Many enterprise systems use both patterns.
6️⃣ DevOps & SRE Perspective
Composite keys improve data integrity in production systems.
They:
Prevent duplicate relationships
Reduce cleanup jobs
Improve join accuracy
Simplify analytics pipelines
They also reduce storage overhead by removing unnecessary ID columns.
However, there are trade-offs.
Some ORMs:
struggle with composite keys
complicate migrations
require additional configuration
This is where engineering judgment matters.
7️⃣ Mental Model to Lock In
Composite keys enforce:
Relationship uniqueness at the database level.
They are not an advanced trick.
They are a core relational modeling tool.
If you understand composite keys, you understand something deeper:
Relational databases are not just storing entities.
They are modeling relationships between entities.
The Bridge Back
Remember the duplicate order bug?
The fix was simple.
We added:
PRIMARY KEY (order_id, product_id)
The database immediately blocked duplicates.
No extra validation code.
No cleanup scripts.
Just a simple rule encoded in the schema.
That’s the power of good data modeling.
Sometimes the most powerful backend logic isn’t written in code.
It’s enforced by the database itself.



