Clickpost's Overflow Check Skipped the Column With No Foreign Key
Clickpost's 54-minute order outage came from a 32-bit column in a deprecated logging table. Its overflow check watched only primary and foreign keys, and this column held IDs without a declared foreign key.
On 2 November 2026, between 16:08 and 17:02 IST, Clickpost's v3 order creation API returned HTTP 5xx errors for most carriers. In its root cause analysis, posted on 3 November, Clickpost traces those 54 minutes to a single column in a logging table it had deprecated in February. The column was a 32-bit signed integer, and the IDs being stored in it passed 2,147,483,647.
Integer overflow on an ID column is an old failure, and most organisations with a large database already monitor for it. Clickpost did monitor for it. What's useful about this report is which columns were being monitored. In the report's words, "Our integer capacity checks covered only primary key and foreign key columns." The column that broke stored IDs from another table, but it was never declared as a foreign key, so the check never looked at it.
How the failure chained
Clickpost has two services that create orders. A newer one, written in Kotlin, handles 91 carriers. An older Python service handles v3 order creation for all other carriers. After an order is created, a post-processing service used to write a log row recording the ID of a related record.
When the logging table was deprecated in a February 2026 release, that write was removed from the Kotlin path but left in the Python path. The related records use IDs without a 32-bit limit, so they kept growing. Around 16:08 IST on 2 November, a new related record got an ID above 2,147,483,647, and the database rejected the log write. Because the write ran synchronously inside the order creation request, every rejection failed the whole order, and customers on the Python path got 5xx errors. Orders for the 91 carriers on the Kotlin service went through.
Monitoring flagged the rise in 5xx errors within a minute. Comparing the two services showed that only the Python side was failing, which led the team to the legacy write to the deprecated table. They disabled that write, and order creation was restored at 17:02 IST.

The check inherited the schema's blind spot
The report names three contributing factors: incomplete decommissioning, gaps in capacity monitoring, and logging in the critical path. The second is the one most likely to be sitting in your own database right now.
The easy way to pick columns to monitor is to read the primary key and foreign key constraints. They are stored in the catalog, the query stays short, and on a well-modeled schema it finds the columns people usually think of as IDs. But the check is only as good as the schema's declarations. Without a declared constraint, a column holding another table's ID looks like any other integer column.
Undeclared references turn up most in the least-maintained parts of a database. Logging and audit tables often leave out foreign keys on purpose, because a constraint on a high-volume append table costs write performance and blocks deleting the parent rows. Columns added in a hurry leave them out by accident. Tables on their way out get no new constraints and no new reviews. Clickpost's column sat in two of those places at once: a logging table holding a reference without a constraint, in a table already marked deprecated.
The column also gave no warning of its own. Its values grew only because a live code path kept copying in IDs from a table that grew without limit. Between February and November, the only change to the logging table was that the numbers in it got larger. A monitor built from declarations had no reason to notice.
The report describes the gap more broadly than foreign keys: "Columns that store IDs from other tables without a declared foreign key, or that hold user-supplied integers, were not monitored." Its corrective actions follow the same line: every integer column that stores IDs or user-supplied values is to be found, monitored, and widened to 64 bits where possible.
Pick columns by what they hold
The fix is to select columns by type and content. A capacity check can list every integer column in the catalog, read its current maximum, and compare that with the limit of its type. Declared keys can still come first, but undeclared columns stay in scope. On very large tables the maximum can come from statistics or a sample, as long as a column whose maximum is climbing fast still gets flagged well before it reaches the ceiling.
Two of Clickpost's other corrective actions make the overflow check matter less. Under one, a table cannot be marked deprecated while any code still writes to it, so the label needs evidence that writes have stopped. Under the other, a logging failure can no longer fail an order creation request. Had the first been in place in February, the write would have been gone before IDs reached the ceiling. Had the second, the overflow would have cost a log row rather than an order.
Still, the most useful thing the incident leaves behind is an audit question. If your overflow monitor builds its list from key constraints, ask how many integer columns in your schema hold IDs and have no declared constraint at all. Those are the columns your alerting cannot see. In Clickpost's case, one of them passed 2,147,483,647 in November, in a table that had been deprecated since February.