SSerguey Asael Shinder
Java coding notes: the JVM, and writing software that lasts

Serguey Asael Shinder: The dangerous default is the one that was correct while there was only one of you

· by Serguey Asael Shinder / Serguey Shinder

Spring Batch added a configurable collection prefix to its MongoDB job repository this week. The JDBC repository had one already. Until the addition, two applications pointed at the same MongoDB database wrote into the same collections, and nothing anywhere said they should not - because for the first application, they were simply the collections.

That is a shape worth naming, because it recurs everywhere and it is invisible from inside the system that has it.

A default is written when there is one of something. One application, one tenant, one host, one environment. In that world the default is not a choice at all: a collection called BATCH_JOB is the job collection, and giving it a configurable prefix would look like ceremony. The second instance is what turns the same value from a name into a collision, and the second instance usually arrives without anyone revisiting the decision that assumed it would not.

Serguey Asael Shinder: The dangerous default is the one that was correct while there was only one of you
The dangerous default is the one that was correct while there was only one of you — Serguey Asael Shinder

The test that catches it early

The question that surfaces this class is not "is this default correct?" but "what does this default mean when there are two of us?" Run it over the configuration you already have and the candidates fall out quickly: a table prefix, a cache key, a lock name, a temporary directory, a metrics namespace, a queue name, a client identifier sent to a shared broker.

Two properties make an instance of this dangerous rather than merely untidy. The first is that the collision is silent - both parties write successfully and the damage is in the mixing. The second is that the fix is a migration rather than a setting, because by the time a second tenant exists the first one's data is already sitting under the shared name.

Which is why the way Spring Batch shipped it is the right way: the prefix defaults to what the collections are already called, so the change is invisible to everyone who has one application and available to everyone who is about to have two. A capability added without a migration is worth more than a better default that requires one.