Skip to docs content
Concepts/The Five Change Cases

Concepts

The Five Change Cases

Add, rename, retype, remove, reorder — each with its Borsh reasoning.

Every diff reduces to a combination of five basic change cases. Each is classified independently against the same rules — so a single edit that widens one field while reordering two others is analysed as three separate changes.

Add a field

SAFEDANGER

Appending a field at the end of the struct is SAFE — nothing before it moves, so existing accounts still deserialize correctly. Inserting a field in the middle shifts every following offset, so under Borsh-by- position it is DANGER: old accounts are misread until migrated. (This is the is_active example used throughout the docs.)

Rename a field

SAFEDANGER

A rename is SAFE only when a field disappears and a new one appears at the same position with the same type and size. If the type or size differs, the tool can’t distinguish a rename from a remove-plus-add, so it treats it as DANGER rather than guess. Confirm true renames in the optional hint file.

Change a field's type

REVIEWDANGER

Widening within the same meaning — say u8 → u16, same signedness — is REVIEW: the value fits and the tool generates a safe conversion, but you should confirm intent. Reinterpreting the bytes — u64 → u128 changes the byte width and shifts everything after it,int → Pubkey, or a signedness flip — is DANGER, because the same bytes now mean something different.

Remove a field

DANGER

Removing a field is DANGER. It has two failure modes: the field’s value is lost permanently, and every field after it shifts offset. check fails by default; with an explicit acknowledgement,gen still scaffolds the mechanical work and marks the human decision. The safe escape hatch is to keep the field and mark it deprecated.

Reorder / shift fields

SAFEREVIEW

Reordering the same fields is SAFE under Borsh, because fields are matched by name on re-serialization — order doesn’t change the bytes. In zero-copy it’s REVIEW (and escalates to DANGER if alignment breaks), because order controls real offsets, padding, and total size.

Why this matters

Knowing your intent isn’t the same as knowing the byte-level consequences. layoutd turns a private “I widened this” into a checked, recorded artifact — and catches the change you didn’t realise you made.

Borsh vs zero-copy changes the answer

Several of these verdicts depend on the account model. A mid-struct insert or reorder behaves very differently under zero-copy, where real offsets and alignment apply. See Borsh vs Zero-Copy.