All you need is PostgreSQL

All you need is PostgreSQL

你只需要 PostgreSQL

June 25, 2026 by Eduardo Bellani 2026年6月25日 作者:Eduardo Bellani

Introduction

引言

There is a deep cultural reflex in modern engineering: whenever a problem appears, reach for a packaged solution instead of thinking from first principles. The result is architectural cargo culting and lots of missed opportunities. Some intentionally absurd-but-familiar examples: We need an audit trail, let’s use {temporal/event sourcing DBMS}. Our application is slow, let’s cache that using {in-memory key-value database}. And since a relational database like PostgreSQL is still considered mandatory, thanks mostly to its unmatched reputation, companies end up stacking product on top of product on top of PostgreSQL. They inflate the number of moving parts, operational risk, headcount demand, and overall system entropy. Complexity grows, not because the problems demand it, but because someone reached for a tool they saw in a conference talk. In this post, I’ll walk through a set of common misconceptions that drive teams to introduce new infrastructure when they don’t need to. All of these can be solved with vanilla PostgreSQL 18 using standard extensions available on RDS, with no special infrastructure and no distributed-systems cosplay. The goal in this article is not to argue that specialized systems are never appropriate, but to show that the default assumption for your data problems should be that my company can do fine with just PostgreSQL.

在现代工程领域存在一种根深蒂固的文化反射:每当出现问题时,人们总是倾向于寻找现成的封装解决方案,而不是从第一性原理出发进行思考。其结果往往是“架构上的形式主义”(cargo culting)以及大量错失的机会。以下是一些故意夸张但又令人熟悉的例子:我们需要审计追踪,那就用 {Temporal/事件溯源数据库};我们的应用太慢了,那就用 {内存键值数据库} 做缓存。由于 PostgreSQL 凭借其无与伦比的声誉,依然被视为关系型数据库的首选,企业最终往往在 PostgreSQL 之上堆叠各种产品。这增加了系统的活动部件数量、运营风险、人力需求以及整体系统熵。复杂性之所以增加,并非因为问题本身需要,而是因为有人使用了他们在技术会议上听到的工具。在这篇文章中,我将剖析一系列常见的误区,这些误区驱使团队在并不需要的情况下引入新的基础设施。所有这些问题都可以通过标准的 PostgreSQL 18 以及 RDS 上可用的标准扩展来解决,无需特殊的架构,也不必进行“分布式系统角色扮演”。本文的目的并非争论专用系统永远不适用,而是要表明:对于你的数据问题,默认的假设应该是——我的公司仅靠 PostgreSQL 就足够了。

The setup

准备工作

Here is a list of arguments that people put forth to reach for other tools besides PostgreSQL, based on my experience: I’ll need auditing and reconstructing state; Write throughput is too low; The transactional queries are too slow; The analytical queries are too slow; My app will be coupled to the Database. To address these, I’m going to use a variation of the Drosophila melanogaster of the database field: the classic Supplier and Parts database (Date 2003). I’ll update it to be more in line with the usual problematic tables: Financial Transaction and their originating transfers. For the rest of this article we will be constructing a database design based on modern PostgreSQL that will achieve the general goals listed above and specific business requirements.

根据我的经验,以下是人们为了在 PostgreSQL 之外寻找其他工具而提出的常见理由:我需要审计和重构状态;写入吞吐量太低;事务查询太慢;分析查询太慢;我的应用会与数据库耦合。为了解决这些问题,我将使用数据库领域的“果蝇”——经典的“供应商与零件”数据库(Date 2003)的变体。我将对其进行更新,使其更符合常见的复杂表结构:金融交易及其原始转账。在本文的后续部分,我们将基于现代 PostgreSQL 构建一个数据库设计,以实现上述通用目标以及特定的业务需求。

Requirements

需求

Here is a requirements snippet from a very popular banking API company: Transactions: are immutable records of financial interactions with Increase. You can think of them as the line items on your bank statement. A Transaction with a positive amount means there’s more money in your account. A Transaction with a negative amount means there’s less money in your account. You can’t directly create a Transaction, and they never change after they are made. Anything that causes money to move around your Increase account results in a Transaction - initiated or received transfers, card payments, earned interest, and more. Transfers: which includes ACH Transfers, Wire Transfers, etc - are the most common way to initiate money movement over external networks with Increase. Transfers are one-to-many with Transactions, which they create as side-effects. Unlike Transactions, Transfers are stateful and transition through a lifecycle of different statuses as they move across the network. Pending Transactions: represent potential future credits or debits of money into your account and are a separate resource from Transactions (despite their similar name). Notably, while Transactions are immutable, Pending Transactions are not, as they don’t guarantee the movement of money. For example, Pending Transactions are created for card authorizations (which can mutate or timeout) and also when placing a hold on an account (which can be removed). Pending Transactions do not affect your current balance (which is the balance you earn interest on), but do affect your available balance (which is the amount you’re able to move out of Increase). (Increase, Inc. 2025)

以下是一段来自一家非常流行的银行 API 公司的需求摘要:交易(Transactions):是与 Increase 进行金融交互的不可变记录。你可以将其视为银行对账单上的明细项。金额为正的交易意味着账户资金增加,金额为负则意味着资金减少。你不能直接创建交易,且交易一旦生成便不可更改。任何导致 Increase 账户资金变动的行为都会产生交易——包括发起或接收的转账、卡支付、赚取的利息等。转账(Transfers):包括 ACH 转账、电汇等,是 Increase 在外部网络上发起资金移动的最常见方式。转账与交易之间是一对多的关系,转账会产生交易作为副作用。与交易不同,转账是有状态的,随着在网络中的移动,会经历不同状态的生命周期。待处理交易(Pending Transactions):代表未来可能存入或扣除的资金,与“交易”是不同的资源(尽管名称相似)。值得注意的是,虽然交易是不可变的,但待处理交易是可变的,因为它们不保证资金的实际移动。例如,待处理交易是为卡授权(可能会变更或超时)以及账户冻结(可能会被解除)而创建的。待处理交易不会影响你的当前余额(即你赚取利息的余额),但会影响你的可用余额(即你可以从 Increase 转出的金额)。(Increase, Inc. 2025)

From these 2 images, here is a list of requirements (functional and not) that I have extracted, which I consider to be common in financial systems like Increase: Accounts are defined by immutable routing numbers and account numbers and have a status that can vary. Accounts are discriminated between external and managed, and one account must be one or the other exclusively. Transfers are made only between external and managed accounts. Transactions and transfers are listed, paginated by their respective creation times. Current and available balance are shown, both their present and historical daily values. Transfers behave like a state machine where the progression between states are exposed to the user. The user can see the full state history of a transfer and some of these states are linked to pending/settled transactions. The user can also see the details of a transaction, and see the transfer that generated it. We should maximize write throughput of transactions and transfers.

基于这些信息,我提取了一份功能性和非功能性需求列表,我认为这些需求在像 Increase 这样的金融系统中非常普遍:账户由不可变的路由号码和账号定义,且具有可变的状态。账户分为外部账户和托管账户,且一个账户必须且只能属于其中一种。转账仅在外部账户和托管账户之间进行。交易和转账列表需按创建时间分页。需显示当前余额和可用余额,包括当前值和历史每日值。转账表现为状态机,其状态演变过程对用户可见。用户可以查看转账的完整状态历史,其中一些状态与待处理/已结算的交易相关联。用户还可以查看交易详情,并查看生成该交易的转账记录。我们应最大化交易和转账的写入吞吐量。