Typing before correctly parsing
October 15th, 2022
Instead of Postgres
serial data type for primary keys, I use random bigint’s for Postgres ids. (This is yet another idea courtesy of Numeracy.) Despite my initial reversion to the idea (what if you have a collision!1), random bigints offer some advantages over
serial. At minimal cost (4 bytes more per row), they obscure an entity’s id while being simpler than uuid’s and they can be trivially shortened by base64 encoding them. For short, secret links like numeracy.co/q/8m0Kx are harder to guess than numeracy.co/q/4.
,string option to struct tags for precisely this. However, I use sqlc to generate Go code (including json struct tags) and this is not currently possible (the
go_struct_tag override doesn’t work for this).
My next thought was creating a custom data type BigInt and using
data_type overrides to force the generated models to use my
BigInt types. This kind of works.
JSON.parse that can’t. Instead of mangling the data, clients can just parse with a library like json-bigint. It all returns to a lesson I learned long ago. Clean interfaces are more important than clean code.
There’s a 50% chance of a collision after 2.5 billion rows, at which point you would have filled up your
serialspace anyways. Given you’re unlikely to have 100% uptime on your way to a billion rows of anything, so clients are usually able to handle failed operations anyways. ↩