The Backend Mindset

I spent years building web services. The instinct was always the same: move fast, push logic to the application layer, let the database handle persistence, and trust that the system you've built today will still be running tomorrow the way you intended it to.

This works in a certain context. You control the deployment. You monitor the logs. If something breaks, you roll back. Your users are known. Your infrastructure is yours.

But it makes you think about authority in a specific way. In backend systems, authority is soft. It's a row in a table saying "this user can do this action." It's a cache that expires. It's a permission check that might be stale. It's a rule that the code enforces, but the code can change. The rule itself isn't immutable—it's a policy you decided on, in a service you control, that you can revise if you need to.

This is fine for most applications. But it's a dangerous assumption to carry into a world where the system you're building might be called by an untrusted client, where your code will eventually be replaced by someone else's code, and where the rules themselves need to outlive your deployment.

That's where I learned I wasn't a backend engineer anymore.


The Moment of Inflection: Solana Summer School

Solana Summer School wasn't supposed to be a turning point. It was supposed to be a way to deepen my understanding of blockchain. I'd been reading about Solana's account model. I'd built toy projects on devnet. But reading about something and building something real with it are different experiences.

The workshop I built around Metaplex Core was small. Walk through a soulbound asset—an NFT that cannot be transferred. Understand how Metaplex implements this. Then rebuild the concept as an Anchor program that performs a CPI into MPL Core to enforce it.

The moment it crystallized was when I realized: the soulbound claim is not a feature you request. It's not a UI state you set. It's not a permission check in a service. It's an immutable rule encoded in the account structure itself.

When you mark an asset with the PermanentFreezeDelegate plugin and immutable authority, you're not saying "this asset cannot be transferred." You're saying "the only way to transfer this asset would require modifying the account in a way that consensus rules forbid." The rule isn't enforced by your code. It's enforced by the chain itself, before your code even runs.

That distinction changed how I think about authority.

A backend rule is: "If the user has permission, let them do this."

A protocol rule is: "It is cryptographically impossible for anyone to do this without permission, and the chain will reject any attempt to violate it."

One is a policy you can change. The other is a law.


The Shift: From Application Rules to Protocol Rules

This is where most backend developers get stuck, and I almost did too.

In application development, you're used to being flexible. A requirement changes, you refactor. A security issue surfaces, you patch. A user needs an exception, you add a flag. Rules are tools you use; they're not the foundation.

But protocol engineering inverts this. At the protocol layer, the rule isn't something you implement. It's something the system enforces, and your job is to make sure the rule is so tightly defined that it cannot be violated—not because your code prevents it, but because violating it would require changing something immutable.

This demands a different kind of rigor. When you're writing an application, you can afford to be approximate. "Success" might mean "the request completed without throwing an exception." "Authorization" might mean "the user has the right role." "Payment" might mean "the database updated and the API returned 200."

But at the protocol layer, those approximations are dangerous. Approximation is where exploits live.

A payment is not successful because your backend says so. It's successful when:

  • The mandate was validated on-chain
  • The tokens were transferred by the approved program
  • The receipt was written to an immutable account
  • The transaction reached finality
  • The receipt fields match the request

Each of those is a separate claim, and each one is verifiable from the system, not from a dashboard or a log message.


Building ChainPay: Where Philosophy Meets Practice

I didn't set out to become a protocol engineer. I set out to solve a practical problem: how do you let AI agents spend money without giving them your keys?

The naive answer is: you don't. Agents can't sign cryptographic transactions. They're not key custodians.

But that's only true if you think of the problem as "agent needs to sign." If you reframe it as "owner authorizes a rule, and the protocol enforces it," the problem becomes tractable.

That reframing is protocol thinking.

ChainPay became practical because I stopped thinking about it as a service that validates payments. I started thinking about it as a set of immutable rules that the chain enforces, and a backend that observes the proof.

A mandate isn't a database row that says "this agent can spend this much." It's an on-chain account that the Solana program reads before executing any transfer. The program checks: Is this the approved agent? Is the amount within the limit? Has the cooldown elapsed? Is the mandate unexpired? Is replay protection satisfied? Only if all those checks pass does the transfer execute.

None of those checks happen in my backend. They happen in the Solana program, at the protocol layer. My backend doesn't decide whether a payment is allowed. It observes the receipt and reports what happened.

This is a different job than application development. It's harder in some ways—you have to think about attack surfaces you've never encountered. It's easier in other ways—you can reason about guarantees that application developers can only dream of.


The Clarity of Constraints

Protocol engineering is clarifying because it forces you to hold contradictory truths at the same time.

A preflight check is not a guarantee. It's useful feedback, but it's not proof. The network state might change between when you run a preflight and when you submit a transaction.

A successful RPC call is not a successful payment. The RPC returned your transaction, but that doesn't mean it will execute, and it certainly doesn't mean it will reach finality.

A confirmed transaction is not a finalized transaction. Solana's confirmation guarantees are strong, but "confirmed" is not the same as "no one will ever reverse this."

A receipt in a database is not a settlement. The database can be rewritten. The blockchain cannot.

Most backend developers never have to hold these distinctions. You send a database write, the transaction commits, and you move on. The database is your source of truth, and you trust it.

But at the protocol layer, the chain is your source of truth, and you have to accept that your backend's view of reality might be out of sync with the protocol's. Your job is to make sure the protocol is right and your backend catches up.

This is uncomfortable at first. It feels like you're giving up control. In a sense, you are. But what you're gaining is certainty. A protocol rule doesn't care what you intended. It doesn't care what your logs say. It just enforces what it was designed to enforce, and that enforcement is verifiable by anyone with access to the chain.


The Turn: From Building Services to Building Rules

I think the moment I became a protocol engineer instead of a backend engineer was when I stopped asking "How do I implement this feature?" and started asking "What is the minimal set of rules that make this feature true?"

Those are different questions.

Feature thinking asks: What code do I need to write? What endpoints do I need to expose? What data do I need to store?

Rule thinking asks: What is true about the world if this works correctly? What would be false if it didn't? What's the smallest immutable statement that captures the essence of this rule?

For payments, the feature thinking leads to building a checkout flow, validating inputs, storing orders, integrating with a payment processor, updating dashboards.

The rule thinking leads to: A payment is verified when the agent authorized by a mandate transferred the exact amount to the exact recipient within the exact limits and time window that the mandate specified, and that transfer is immutable and on-chain.

One of those leads to a service. The other leads to a protocol.


What This Costs

Protocol engineering is demanding in ways that backend development isn't.

You have to hold multiple layers of abstraction in your head at once: the user intent, the application logic, the protocol rules, the chain constraints, the economic incentives. You have to reason about what happens when every assumption you made is violated.

You have to accept that you can't iterate as fast. In backend development, you can deploy a new version of your service in minutes. At the protocol layer, you might have to wait for finality, verify on-chain state, test against multiple settlement layers.

You have to be comfortable with uncertainty. The chain doesn't give you transaction logs or support tickets. It gives you immutable accounts and cryptographic proofs. You have to become fluent in reading those.

And you have to resist the urge to flatten complexity into a single "success" state. It's tempting to let the backend say "the payment succeeded" when the transaction is in the mempool. But eventually, someone will build a system that relies on the difference between "in the mempool" and "finalized," and if you've already blurred that line, you've broken their assumptions.


The Clarity This Gives

But the payoff is immense.

Once you've shipped a protocol, you're done shipping it. Not "done for now." Not "done until the next security audit." Done. The rules are written. They're on-chain. They're enforced by consensus. You can't change them without hard forking, and you're not going to do that.

This forces you to think deeply, because you can't iterate your way out of mistakes. You have to get it right before you deploy.

It also gives you a kind of peace that backend engineering doesn't. In backend systems, you're always worried about the next edge case, the next attack vector, the next requirement change. You're managing complexity. In protocol engineering, you're encoding simplicity. You define the rules, and the chain enforces them. No edge case surprises. No hidden behaviors. The system does exactly what the protocol says, and nothing else.

And for the users of your protocol—the agents, the developers, the operators—there's a clarity too. They can read the rules themselves. They don't have to trust your dashboard or your documentation. They can verify the behavior against the code, and the code is immutable.


Where I Am Now

I'm still early in this journey. My Rust is improving. My understanding of Anchor and Token-2022 deepens with every program I write. I'm learning to see financial and coordination problems in terms of rules and accounts and CPIs instead of in terms of services and databases and APIs.

But I'm not trying to become a Solana expert or a blockchain specialist. That's the wrong framing. I'm trying to become the kind of engineer who can take a real problem—AI agents need bounded financial authority, or organizations need to enforce a governance rule, or a market needs verifiable settlement—and distill it into the smallest possible set of rules that the protocol can enforce.

That's the work. That's the discipline.

Solana Summer School made the account model tangible. Building ChainPay turned the lesson into a practice. The workshop walks through the idea; ChainPay is where it becomes real.

The protocol engineer asks: not "How do I build this?" but "What is the minimum immutable truth that makes this work?"

That question changes everything.


Related:

  • Building a Universal MCP for Agent Payments
  • When Koyeb and Heroku Both Ghosted Me: A TypeScript Compiler Meltdown
  • ChainPay on Devnet

Tags: #ProtocolEngineering #Solana #SmartContracts #SystemsDesign #SolanaSummerSchool #ChainPay #BoundedAuthority #Anchor