We had the same session written twice —one copy per application— and a shared library to stop duplicating it. The token looks identical in all three: id|version|expiry|signature, an HMAC-SHA256 over the payload.
The temptation was obvious: «same three-field format, the migration is transparent, live cookies keep working». We took it for granted.
Before touching anything we computed the signature of one payload with both implementations and compared it against the library's real fixed vector —a frozen token, pasted as a literal in the tests precisely for this—. They didn't match.
The cause wasn't the format. As it hardened, the library had started prepending the length of the signing domain to the HMAC message (a fix against a prefix ambiguity). With the empty domain of a normal session that already changes the message: one signature is HMAC(payload) and the other HMAC([8 zero bytes]‖payload). Same text, different signature.
Consequence: migrating to the shared library logs every user out on deploy. It's not a bug —the library is stricter, not weaker— but it's a real disruption you decide and announce, not one you discover in production.
The method lesson: a round-trip test —issue and verify with the same binary— measures the codec against itself. It stays green even if you change the separator, the field order or the base64 engine… and it would log everyone out without a single red test. The only thing that discriminates is a fixed vector: a real frozen token, verified by today's binary. If it goes red, what was stored stopped being readable —and that gets decided, not regenerated—.
The rule we kept: signature compatibility isn't read off the format. You measure it against a frozen artifact before claiming «compatible with what's already issued».
Xiliux