Coding Agents, Starter Kits and Pgledger Paul Gross added idempotency support to pgledger, his ledger implementation built entirely in PostgreSQL, reversing a long-held reluctance to add the feature. Gross wrote that coding agents now let users adapt the starter kit with prompts such as "Add pgledger to my app" or "Change the ID format to match our existing conventions," which shifted his criteria for what belongs in pgledger itself toward features that are widely requested, complicated, or deeply integrated. Idempotency ensures a repeated ledger operation is performed only once, covering cases where a request or connection times out or a multi-stage operation's retry safety is unclear. Coding Agents, Starter Kits and pgledger https://www.pgrs.net/2026/10/29/coding-agents-starter-kits-and-pgledger/ I’ve been working on a ledger implementation in pure PostgreSQL called pgledger https://github.com/pgr0ss/pgledger . For the backstory, please read my previous blog post: Ledger Implementation in PostgreSQL https://pgrs.net/2025/03/24/pgledger-ledger-implementation-in-postgresql/ . Libraries vs Starter Kits pgledger is not a software dependency in the traditional sense. It’s not a package to install, or a library to depend on. Instead, it’s a set of database tables and SQL functions that need to be added to your application. The way you add it depends on the existing technical stack. Wherever you add migrations, that’s where you’ll add the database tables and SQL functions. However you run SQL, that’s where you’ll add the calls to create ledger transfers. Oftentimes, when someone adds pgledger to their app, they will want to make a few changes. For example, maybe they want to add extra foreign keys to their existing tables e.g. pgledger accounts will have foreign keys to their users table . Or maybe they want to enforce a certain subset of currencies. Or maybe they want to change the pgledger ID generation https://github.com/pgr0ss/pgledger ids to match their existing patterns. In this way, I think of pgledger as a starter kit for a ledger. You begin with pgledger and then adapt as necessary. In the past, this would all be manual - copy the SQL to your codebase, and then make changes as desired. Now, the rise of coding agents changes this dramatically. A simple agent prompt like “Add pgledger to my app” or even “Add a postgresql based ledger” will go out, fetch pgledger, and adapt it for the current codebase. Customizing pgledger is also easier with further prompts, such as “Add foreign keys to my other related tables” or even “Change the ID format to match our existing conventions” . Feature Tension Before coding agents and easy customizability, I assumed that pgledger would be used almost exactly as written with few changes. Therefore, I wanted to keep it pretty small and simple, and I was hesitant to add extra features. Now, I feel like there are competing tensions: 1. It’s easy for coding agents to add features people need, so I don’t need to add much to pgledger itself and I can let folks customize as needed. 2. It’s easy for coding agents to remove features people don’t want, so as a starter kit, I should add lots of optional features and folks can remove the ones they don’t plan to use. Current Thoughts Given these tensions, I think there are a few considerations and criteria for when a feature is worth adding to pgledger itself: 1. Widely requested - A feature that will be used by a significant portion of people is a better candidate for adding than one that is only for a very small number of apps. 2. Complicated - If a feature is sufficiently complicated, relying on an agent to add it later is risky. If I add it to pgledger myself instead, I can ensure it is well designed and well tested e.g. with both regular tests and property tests . 3. Integrated - An integrated feature is harder to add than something at the edges. For example, adding extra foreign keys is easy, but changing the core PostgreSQL functions is harder and riskier. Idempotency Support My change in thinking has led me to add idempotency support to pgledger. Idempotency for a ledger is the idea that repeating the same operation multiple times is safe, and will only perform the action once. This helps with cases where a caller might not be sure the operation succeeded. For example, a request or connection times out. Or the ledger piece is part of a multi-stage operation, and it’s not clear which parts are safe to retry and which are not. I resisted adding idempotency support to pgledger for a long time, mainly because most apps I’ve worked on already had idempotency support in a different layer. For example, API requests supported idempotency via a header, so as long as the request handling was in the same database transaction as the pgledger operations, everything was idempotent together. However, given the current criteria, I changed my mind and decided to add it. This is a feature which has been requested many times both in GitHub issues and separately . It’s complicated to implement correctly. And it’s integrated into the core functions. But if you don’t want or need it for your app, it’s also pretty straightforward for an agent to remove i.e. easier to remove code than add it correctly . Idempotency Details in pgledger Now, a caller can pass in an idempotency key along with each pgledger create transfer . If the idempotency key hasn’t been seen yet, a new transfer will be created. If the idempotency key already exists, the existing transfer will be returned instead of a new one. For example: -- First call creates a new transfer select id from pgledger create transfer 'pgla 1', 'pgla 2', 12.34, idempotency key = 'a-random-uuid' ; id --------------------------------- pglt 01M61YEM35E2TSA4Z4XG01Q8X0 1 row -- Second call reusing the idempotency key returns the existing transfer select id from pgledger create transfer 'pgla 1', 'pgla 2', 12.34, idempotency key = 'a-random-uuid' ; id --------------------------------- pglt 01M61YEM35E2TSA4Z4XG01Q8X0 1 row Reusing an idempotency key with a different set of arguments causes an error: select id from pgledger create transfer 'pgla 2', 'pgla 1', 43.21, idempotency key = 'a-random-uuid' ; ERROR: Idempotency key a-random-uuid was already used with a different request Read more about the feature in the README https://github.com/pgr0ss/pgledger idempotency . Final Thoughts Coding agents make it easier to write and assemble working software. They are great at finding existing solutions and adapting them. So I think hardened, thoroughly tested components are more important than ever. That’s why I built pgledger https://github.com/pgr0ss/pgledger , since ledgers are critical to get right at the start. And by making it easier to include robust ledgers, I hope that apps will use them in more places. 1 fn:1 Share on Bluesky https://bsky.app/intent/compose?text=Coding+Agents%2C+Starter+Kits+and+pgledger%20https%3A%2F%2Fwww.pgrs.net%2F2026%2F10%2F29%2Fcoding-agents-starter-kits-and-pgledger%2F