Most carbon offsets fail at the checkout. The booking confirms, the receipt sends, and somewhere off to the side a separate process is supposed to fire — a webhook to a registry, a nightly batch job, a quarterly reconciliation with a broker. Sometimes it works. Sometimes it doesn't. Sometimes it works but the buyer never sees it, so the climate claim sits unverifiable on a marketing page. We built IMPT to remove that whole class of failure. The booking and the offset are one transaction. If the booking lives, the tonne is retired. If the retirement fails, the booking doesn't go through. That is what we mean by atomic offset, and it is the pattern I want to walk through here.
What "atomic" actually means
In databases, atomic means a transaction either fully completes or fully reverts. There is no middle. You don't end up with money debited and goods unshipped, or a seat sold twice. The same property is what makes smart contracts useful for climate work. A Solidity function call either runs end-to-end or it reverts and leaves no trace. That is a much stronger guarantee than the usual web2 stack of API calls glued together with retries and hope.
The naive web2 pattern for a "carbon-neutral booking" looks like this: take the payment, send the booking to the supplier, queue a message to an offset provider, log an internal counter, send a confirmation email that promises the offset is "on its way". Each of those steps can fail independently. The offset provider can be down. The queue can drop the message. The counter can drift. The email goes out anyway. Three months later, somebody asks for proof and the proof is a CSV that was reconciled by a person.
The atomic pattern collapses that into a single state change. The user pays. The contract takes the payment, settles the supplier leg, and burns or retires the carbon credit in the same call. No outbox, no nightly job, no human in the loop. If the credit isn't there to retire, the function reverts and the user is told the booking can't be completed under the current climate budget. That last part matters and I'll come back to it.
The shape of the contract
You don't need to read Solidity to follow this. The structure of an atomic offset-on-purchase contract has four moving parts:
- A booking entrypoint that takes the user's payment and the booking reference from the supplier API.
- A retirement module that holds, or has authority to pull from, a pool of pre-verified carbon credits.
- A receipt — an event emitted on-chain that ties the booking reference to the specific tonne retired, with the project ID, vintage, and serial.
- A revert path for when any of the above fails, so no half-state escapes.
The interesting design choice is where you put the credit. You can hold a live pool inside the contract, you can use an oracle to call out to a registry, or you can pre-mint tokenised credits that represent already-retired tonnes. Each has trade-offs. A live pool is simplest but ties up capital. An oracle introduces an external dependency that can fail or be gamed. Pre-tokenised retired credits are clean but shift the trust question one step earlier — you have to trust the tokenisation.
We've gone with a model where IMPT funds the offset out of its own commission on the booking, not the user's wallet. The user pays for the room. The contract pulls the tonne from our climate budget and retires it against their booking. The user gets the proof. They didn't pay extra. They didn't have to opt in. That's what climate-default means.
Why the same transaction, not the next one
People sometimes ask why this needs to be on-chain at all. Couldn't you just promise to offset every booking and publish a quarterly report? You could. The industry did that for a decade. It produced the offset scandals you've read about — double-counting, phantom credits, projects that never broke ground, retirements that were "pending" forever.
The reason to put it in the same transaction is that it makes lying expensive. If the retirement event is emitted at block n with the booking reference, anybody can verify it. The serial number of the tonne is in the log. Two bookings cannot share a serial. The marketing claim and the on-chain record are the same artefact. Nobody is reconciling them after the fact because there is nothing to reconcile.
It also makes the climate budget a hard constraint instead of a soft one. If the contract can't find a tonne to retire, the booking can't complete. That sounds like a bug. It is actually the feature. It forces the operator — us — to keep the climate side of the balance sheet provisioned. You cannot oversell tonnes the way airlines oversell seats, because the contract will not let you.
What this looks like for the user
From the user's side, none of the above is visible. They search for a hotel. They pick one. They pay. They get a confirmation that includes a link to the on-chain proof of the tonne retired against their stay. That's it. No checkbox. No upsell. No "would you like to add a £2 carbon contribution?" — which, by the way, is the single most depressing UX pattern in modern travel, because it converts climate responsibility into an emotional tax on the buyer.
We have 1.7M hotels in the inventory across 195 countries. The same contract pattern fires on a city break in eco-hotels in Galway as on a long-haul stay in Singapore. The supplier doesn't have to integrate anything new. The user doesn't have to learn anything new. The only thing that changes is that the climate work is done, on-chain, in the same breath as the booking.
The failure modes you actually have to design for
I want to be honest about where this gets hard, because the pattern isn't a free lunch.
Gas and throughput
Every retirement is a write. On a high-fee chain at peak load, that write is expensive and slow. You solve this with the chain you choose, with batching strategies that don't break the atomicity guarantee for the user, and with off-chain order matching that settles to chain at the right cadence. There are several reasonable answers here; there is no zero-cost answer.
Credit quality
The contract can guarantee that a tonne was retired. It cannot, by itself, guarantee that the tonne represents a real avoided or removed emission. That is a question about the upstream project, the methodology, the verifier, and the registry. Atomic offset removes the bookkeeping fraud surface. It does not remove the methodology question. We treat those as separate problems and work them separately.
Reverts the user doesn't understand
If the climate side fails, the booking fails. That is the right behaviour, but you owe the user a clear message. "We couldn't complete this booking under the current climate budget, please try again in a few minutes" is a sentence most people have never seen at a checkout. The first time we shipped this pattern internally, the error copy was the part that took the longest to get right.
Why this matters past hotels
Hotels are where we started, because the booking flow is simple, the supplier APIs are mature, and the unit economics work. The pattern generalises. Any purchase where there is a defensible per-unit emissions figure can be wrapped this way: flights, freight, fuel, e-commerce shipments, ride-hailing, cloud compute. The 20,000+ brands in the IMPT shopping side of the platform are the second front. The forthcoming AI-native booking agent is the third — because once an agent is making bookings on your behalf, you really do want the climate accounting to be a property of the transaction itself, not a setting the agent might forget to toggle.
The broader point is about defaults. The web2 climate stack is opt-in by construction. You have to remember to tick the box. You have to trust the report. You have to reconcile the spreadsheet. The smart contract carbon pattern flips the default. The climate work happens because the transaction happened, not because somebody downstream remembered to make it happen.
What to do this week
If you're an engineer at a booking platform, a marketplace, or a logistics business, the action is small and concrete. Open the code path that handles a confirmed purchase. Count the steps between "payment captured" and "any climate claim you make in marketing". If that count is greater than zero in-transaction steps, you have a reconciliation problem hiding in your stack, and you will eventually have to defend it. If you want to see what the atomic version looks like in production, book a stay through IMPT and pull the on-chain receipt — the serial, the project, the vintage are all there. We're shipping the AI-native booking agent on top of the same contract pattern, and we'll keep writing about what breaks when we scale it. The point of doing this in public is so that the next platform doesn't have to invent it from scratch.