August 29, 2026 · 7 min read
You can't edit a contract, and that's the point
What changes when your CRM finally has an object that behaves like a commitment — it locks, it can't be deleted, and every amendment is an event with its own identity.
I built four hundred contracts on a client's renewal book recently, found a pricing error in fourteen of them, and discovered there was no way to correct it. Not a permissions problem. There is no edit. A contract line item is written once, and after that the only move available is to terminate the agreement and build it again.
My first reaction was that this was a gap in a young object. I've come around: it's the most interesting thing about it, and most of what's worth knowing follows from it.
A record that behaves like an instrument
Everything else in a CRM is a record. Records get edited. Somebody fixes a close date, corrects a name, adjusts an amount, and the object simply becomes the new version of itself. There's usually a history table if you go looking, and almost nobody does.
A contract doesn't work that way. It locks at creation. It can't be deleted — archive is refused and so is delete, and the only terminal state available is termination, which leaves the record in place saying what it said. Amendments aren't edits either; they're separate objects with their own effective dates, attached to the contract they change.
That's not a database being awkward. That's an object modelled on how a commitment actually behaves in the world. You don't edit an agreement you both signed. You amend it, and both versions remain true — the original for the period it governed, the amendment from its effective date forward. The system is enforcing something your legal and finance teams already believed and your CRM previously had no way to represent.
The practical consequence, first
Build your generator so a complete rebuild is cheap, because you will rebuild. Correcting fourteen contracts meant terminating fourteen and regenerating them from source. That was a twenty-minute job because the build was scripted and repeatable. Had those been assembled by hand it would have been a fortnight and a negotiation.
Three clocks, and most fields only hold one
Every contract carries three different dates that teams routinely collapse into one, and the collapse is invisible until something depends on the distinction.
- Effective
- When the agreement governs from. This is the legal clock — what the customer agreed to and when it starts applying.
- Billing
- When money is actually asked for. It often equals the effective date and frequently doesn't — deferred starts, mid-month anchors, a first invoice held back until something is delivered.
- Recognition
- When finance is allowed to count it. This one usually lives in another system entirely and gets reconciled by hand against whatever the CRM says.
Worth knowing before you plan a migration: on a contract with billing switched on, the effective date can't be backdated. It clamps to today. Which means an agreement that genuinely started in March cannot be represented as having started in March once billing is live — a real constraint that shapes whether you bring history across at all, or start the object from the next renewal and leave the past where it is.
Where the term actually lives
Most teams hold contract length in a field on the deal, because that's how people say it. Three-year deal. But the system doesn't read that field and can't. Term is derived from the recurring line item — specifically the number of payments it's set to make. Three annual payments is a three-year agreement, and that's the fact the billing schedule runs on.
This matters more than a modelling quibble. A text field saying three years drives nothing, enforces nothing, and will disagree with the line item inside a quarter. Meanwhile the line item is quietly correct and nobody is reading it.
The inverse case is the one I'd actually check first. A recurring line with no payment count set to renew automatically is saying something specific: this runs until somebody cancels it. In the book I was working through, roughly three quarters of customers were on exactly that footing — renewing annually, indefinitely, with no end date anywhere. Not because anyone decided it, but because there had never been a field for it, so it wasn't written down. Being able to state it is most of the value of the object.
Change is an object, and it carries consent
Amendments come in two shapes, and the difference between them isn't technical. A direct change is applied to the contract by whoever has the rights to make it. A change quote goes to the customer, who signs it, and the amendment lands when they do.
Same effect on the data. Completely different position on whether the customer agreed. And because both are available on the same object, you now have to answer a question the old workarounds let you avoid: which changes can someone make on their own authority, and which ones require the customer to re-sign?
A correction to something you got wrong internally is a direct change. A price increase at renewal is not, no matter how routine it feels or how clearly it's covered by the original terms. Most teams have never had to draw that line explicitly, because there was no object capable of telling the difference. Now there is, and the line gets drawn either deliberately or by whoever is fastest with the tooling.
One mechanical note that costs an afternoon if you meet it cold: each line carries a generated key that amendments target, and you need it to change that line later. It comes back when the contract is created. Keep it. And a contract holding pending changes can't be terminated until those changes are cleared, which is exactly the kind of thing you find out mid-rebuild.
You can stage the whole thing without telling anyone
The most useful thing I found isn't documented as a feature. Billing can be enabled while invoicing stays off — the contract carries real billing dates and a real schedule, and generates nothing. No invoice, no email, no customer-visible artifact.
That let me build an entire renewal book, four hundred agreements, and hand it to the client's finance lead to review as records before a single customer saw anything. She found real problems in it. We rebuilt, she reviewed again. None of that reached a customer, because nothing was live in the sense that matters.
Any migration onto this object should run that way. The alternative is going live to find out whether you modelled it correctly, on records that lock.
The seam nobody plans for
Here's the part I'd want to know before committing to a date, and it's the part that isn't about data modelling at all.
In that book, two hundred and four customers had a card already on file. They'd given it once, at checkout, some of them two years ago, and they get charged at renewal without being asked again. That arrangement is not part of the contract record. It sits with the subscription the contract is replacing.
So the honest question on any migration onto contracts isn't whether the line items are right. It's what happens to the stored payment arrangements — and if the answer is that two hundred and four customers get asked to re-enter their card, that is not a migration anyone should sign off, because you'd be putting a renewal book at risk to change an internal data model. That's a bad trade at any size.
I don't have a clean answer to it yet and I'd distrust anyone who says they do. What I'd insist on is that it gets asked at the start, in the room, before a cutover date exists — rather than discovered in the week you planned to go live.
What it actually changes
For years the honest answer to what is this customer currently committed to was assembled: a deal somewhere carrying the question, a few date properties, a secondary record standing in for renewals, and somebody who knows. Those workarounds were often elegant. They were the only move available.
Now there's an object for it, and it behaves like the thing it represents — it locks, it keeps its history, and it distinguishes between a change you made and a change the customer agreed to. That's a better model. It's also a stricter one, and strictness surfaces decisions that were previously left implicit, mostly about who is allowed to do what.
So the work isn't really configuring an object. It's deciding what one contract means in your business, which of the three clocks each of your dates is holding, and who can change a commitment without asking. Get those three settled and the build is mechanical. Skip them and you'll encode whatever your tooling happened to make easy — permanently, on records you can't edit.