Right, let’s get this out of the way first: you’re not using software designed last week. You’re using a system with the architectural equivalent of a fascinating family tree, complete with brilliant ancestors, a rebellious youth, and a very sensible, stable adulthood. Understanding this history isn’t just academic; it explains the quirks, the power, and the occasional “what were they thinking?!” moments you’ll encounter. So, let’s start at the beginning, before it was even called PostgreSQL.

The INGRES Predecessor: Where It All Began

It all started in the 1970s at UC Berkeley with a project named INGRES (which stands for Interactive Graphics Retrieval System—a name as graceful as a brick). Led by the legendary Michael Stonebraker, INGRES was a groundbreaking relational database. It proved the concept worked, but Stonebraker and his team quickly ran into the fundamental limitations of the relational model itself. They realized that for complex applications like computer-aided design or geographic information systems, just having integers, strings, and dates wasn’t going to cut it. You needed to store more complex, structured data. Trying to model a CAD drawing by breaking it down into a million relational tables is a special kind of madness. This frustration was the direct catalyst for what came next. They had to build something new.

The Postgres Breakthrough: The Post-INGRES Project

So, in 1986, they did. They called it Postgres, meaning “post-Ingres”. The core idea was radical: forget the rigid relational model where you have to fit your data into neat, rectangular tables. Instead, let users define their own objects and their own behaviors. This was an object-relational database. Its killer feature was extensibility. You could define new data types (like a ‘point’ or a ‘circle’), new functions to operate on them (like ‘distance’ or ‘area’), and new kinds of indexes to find them quickly. The query language, POSTQUEL, was designed for this navigational, object-oriented style. It was brilliant, ambitious, and, frankly, a bit of a beast to run. It required a vacuum daemon—not a Hoover, but a process called vACUUM (yes, in mixed case, because why not?) to clean up after its novel multi-version concurrency control (MVCC) implementation. This was the foundation of everything we have today, especially that MVCC magic.

The SQL Takeover: When Good Ideas Get Assimilated

Here’s where history gets funny. While the Postgres team was building their elegant, complex paradise, a simpler technology from IBM was eating the world: SQL. By the early 90s, SQL had won. The market didn’t just want power; it wanted standards. So, in a move of pure pragmatism, the team replaced the POSTQUEL query language with SQL. They didn’t just bolt it on; they integrated it deeply, allowing SQL to interact with all those custom objects and types. This was the birth of Postgres95, a major effort led by Andrew Yu and Jolly Chen. It was lighter, faster, and suddenly spoke the lingua franca of databases. This is a crucial lesson: the best technical solution doesn’t always win. The one everyone can use does.

The Open Source Evolution: Becoming PostgreSQL

Postgres95 was a proof of concept. The real metamorphosis began in 1996 when the baton was passed to the global open-source community. The name was formally changed to PostgreSQL to reflect its new SQL-based heart, and a dedicated team of volunteers took over development. This is where it went from a cool academic project to the robust, industrial-strength system you use today. This community didn’t just fix bugs; they overhauled everything. They replaced that fussy vACUUM daemon with the auto-vacuum launcher we know and love (well, tolerate). They added countless features: write-ahead logging (WAL) for proper durability, hot backups, sophisticated query planning, and later, window functions, common table expressions, and all the other goodies. The core insight from the Postgres days—extensibility—remained. This is why you can do things in PostgreSQL that are unthinkable elsewhere.

-- A tiny example of that original DNA: creating a custom type and operator.
-- First, let's define a new data type (a classic Postgres move).
CREATE TYPE inventory_item AS (
    name        text,
    supplier_id integer,
    price       numeric
);

-- Now, let's create a table that uses it. See? Not just integers and text.
CREATE TABLE on_hand (
    item      inventory_item,
    count     integer
);

INSERT INTO on_hand VALUES (('fuzzy dice', 1, 9.99), 1000);

-- And we can even create a custom operator to compare our items.
-- This is the ultimate expression of that Berkeley extensibility.
CREATE FUNCTION inventory_item_eq(inventory_item, inventory_item)
RETURNS boolean AS $$
    SELECT $1.name = $2.name AND $1.supplier_id = $2.supplier_id;
$$ LANGUAGE SQL;

CREATE OPERATOR = (
    leftarg = inventory_item,
    rightarg = inventory_item,
    procedure = inventory_item_eq,
    commutator = =
);

Why This History Matters to You Today

You might think this is all ancient history, but it’s not. It’s the reason your database doesn’t lock the entire table when someone reads a row (thank you, MVCC). It’s the reason you can use JSONB and query it lightning fast (thank you, GiST index access method, another Postgres concept). It’s the reason you can write stored procedures in Python, or create a column that’s a Fibonacci sequence. That initial design goal—to be extensible—is PostgreSQL’s superpower. The downside? This glorious heritage also explains some rough edges. The vACUUM process, while vastly improved, is still a thing you have to monitor. Some of the catalog tables (pg_class, pg_attribute) feel a bit arcane because they had to support both tables and objects. But I’ll take that trade-off any day. You’re not using a product designed by a corporate committee. You’re using a system built by engineers, for engineers, with a history of solving real, hard problems. Now let’s dig into what all that history actually built.