Cómo funciona PostgreSQL: servidor, almacenamiento y acceso


Este tema no explica cómo se instala (eso viene en la siguiente parte de esta serie) ni cómo se diseña un schema. Aquí se responde una pregunta más de fondo, que surge apenas empiezas a usar una base de datos de verdad: ¿qué es PostgreSQL físicamente, dónde viven realmente los datos, y cómo se accede a ellos igual en local que en la nube?

1. Qué es: un servidor, no un archivo

PostgreSQL no es un archivo que abres (como un Excel o un CSV). Es un servidor: un programa que se queda corriendo, escuchando en un puerto (por defecto el 5432), y con el que se habla enviándole consultas SQL.

La analogía que lo ordena todo:

PostgreSQL es una biblioteca con un bibliotecario. Los libros (tus datos) están dentro, pero solo el bibliotecario (el proceso postgres) sabe interpretarlos. Tú no entras a agarrar libros: tocas la puerta, te identificas (usuario/contraseña) y le pides libros con SQL. Si la biblioteca está cerrada (servidor apagado), los libros siguen ahí en disco, pero nadie puede leerlos.

Consecuencia clave: los datos y el servidor son cosas separadas. El servidor se enciende (y se apaga en las pruebas); los datos persisten en disco independientemente.

2. La jerarquía de 4 niveles

Cuando decimos "mi base de datos", en realidad hay cuatro cosas apiladas que se crean en momentos distintos:

1. SERVIDOR / INSTANCIA   → el proceso 'postgres' corriendo (escucha en 5432)
        │
2. CLUSTER / ALMACÉN      → una carpeta en disco (el "data directory")
        │                    aquí viven TODAS tus bases juntas
        ├── postgres          (base de sistema)
        ├── otra_base         (otro proyecto)
        └── tareas            ← 3. UNA BASE DE DATOS concreta
                 │
                 └── tasks    ← 4. UNA TABLA (+ sus filas)
  • Un mismo servidor guarda muchas bases distintas. En una misma instalación pueden convivir la base de un proyecto y la de otro, sin mezclarse.
  • En Mac (Homebrew) el almacén vive en /opt/homebrew/var/postgresql@17.
  • Postgres no usa los nombres bonitos en disco: cada base es una carpeta-número y cada tabla un archivo-número (OIDs, identificadores internos). Ej: la tabla tasks puede vivir en base/16482/16484 donde 16482 es el OID de la base y 16484 el de la tabla.

3. Los 4 momentos: instalar ≠ encender ≠ crear base ≠ crear tablas

Cada nivel se "arma" en un momento distinto. Confundirlos es el error típico:

Momento Comando (nativo en Mac) Qué nivel arma
Al instalar (una vez en la vida) brew install postgresql@17 corre initdb por dentro Nivel 2: crea el almacén en disco + las bases de sistema + el superusuario
Al arrancar brew services start postgresql@17 Nivel 1: enciende el servidor sobre ese almacén. No crea nada nuevo
Al crear la base createdb tareas Nivel 3: crea la base tareas, vacía
Al crear la estructura psql -d tareas -f init.sql Nivel 4: crea las tablas y mete las filas

¿Y psql postgres? No aparece como momento porque no arma ni enciende nada: es el cliente con el que te conectas al servidor ya encendido para hablarle en SQL. Con la analogía de la biblioteca: brew services start abre la biblioteca; psql es entrar a hablar con el bibliotecario. Si el servidor está apagado, psql no lo arranca — simplemente falla la conexión. Detalle de la sintaxis: postgres ahí es el nombre de la base a la que entras (el comando es psql <nombre-de-base>, ej. psql tareas). Se entra por postgres porque es una base de sistema que siempre existe desde la instalación — el lobby garantizado del servidor cuando todavía no tienes bases propias.

4. Cómo se accede a los datos

Para leer/escribir datos, siempre el mismo proceso, en local o en la nube:

  1. El servidor tiene que estar encendido (si no, "connection refused").
  2. El cliente se conecta con una cadena de conexión: dirección + puerto + usuario + contraseña + nombre de base.
  3. Se mandan consultas SQL (SELECT, INSERT, UPDATE, DELETE).

Cualquier herramienta que se conecte a PostgreSQL — un script de Python, un backend, DBeaver, Power BI — hace exactamente esto: presenta la cadena de conexión y manda SQL.

5. Cómo se almacenan los datos: binario en disco, no CSV

Esto se comprobó mirando los bytes reales de una tabla:

  • El archivo de una tabla es de tipo data (binario). Abrirlo "como texto" da basura (^@^@^@�T�...).
  • Está organizado en páginas de 8 KB — la unidad mínima que Postgres lee/escribe del disco. Aunque la tabla tenga 2 filas, ocupa una página entera.
  • Los textos sí se ven legibles dentro del binario (ej. el título de una fila aparece como cadena), pero están envueltos en estructura binaria: encabezados de fila, punteros, longitudes. Sin el "mapa" que solo Postgres tiene, no sabes dónde empieza y termina cada dato.
  • Una base recién creada ya pesa varios MB con cientos de archivos, aunque tenga pocas filas: cada base carga su propio catálogo de sistema (pg_class, pg_attribute...), las tablas internas donde Postgres guarda "qué tablas y columnas existen".

5.1 Por qué binario y no un CSV (la razón a escala)

CSV / Excel Postgres (binario + páginas)
Buscar 1 fila entre 100.000 Leer línea por línea desde arriba Saltar directo a la página exacta con un índice
Modificar 1 fila Reescribir buena parte del archivo Reescribir solo su página de 8 KB
Varios escribiendo a la vez Se corrompe Control de concurrencia por fila

Un índice es el catálogo de la biblioteca: en vez de recorrer los estantes uno por uno, consultas la ficha y vas directo al estante exacto. Merece su propio post más adelante.

Todo el formato binario existe para una cosa: encontrar y modificar filas rápido sin leerlo todo — justo lo que un CSV no puede a escala. Con 100.000 filas la tabla ocupa cientos de páginas (varios MB), y si supera 1 GB Postgres la parte en varios archivos automáticamente.

5.2 Sacar los datos afuera: exportar

Como el archivo binario solo lo entiende el servidor Postgres (misma versión, su catálogo), no se puede copiar a otro lado y "abrir". Para una copia portable o legible se exporta:

  • pg_dump → respaldo (script SQL o formato propio) para restaurar en otro Postgres.
  • COPY tasks TO 'archivo.csv' CSV HEADER → las filas como CSV real, para Excel u otra herramienta.

Regla: binario por dentro para velocidad; se exporta a CSV/SQL cuando hay que sacarlo afuera.

5.3 Matiz de precisión: disco, no "memoria"

Postgres usa dos cosas distintas:

Qué es ¿Sobrevive a un reinicio?
Disco (almacenamiento persistente) El data directory: donde viven los datos
RAM (memoria volátil) Espacio de trabajo para procesar/cachear queries No

Los datos viven en disco; la RAM es solo la mesa de trabajo. Por eso Postgres necesita un entorno con disco persistente.

6. El servidor y quien se conecta tienen vidas separadas

El servicio que desea conectarse a la base de datos — un backend, un script de Python, una herramienta de BI — no la arranca ni la "despierta". Son dos servicios independientes: la base tiene que estar corriendo antes de que el cliente se conecte. Si está apagada, la conexión falla — y el cliente no tiene el poder de encenderla.

¿Y no debería estar siempre encendida? Sí — en producción una base corre 24/7. Pero "siempre encendida" también tiene momentos de arranque: un despliegue, un reinicio del servidor, una caída. Y cuando la base y el servicio que la usa arrancan a la vez, la base tarda más (segundos) que el servicio (milisegundos). Por eso todo sistema que orquesta varios servicios incluye un mecanismo de "espera a que la base esté lista" (healthcheck): la solución nunca es que el cliente encienda la base (imposible), sino que espere.

7. En local vs en la nube: el acceso es idéntico (lo que cambia es quién administra)

PostgreSQL es el mismo motor en todos lados: almacén binario en disco + acceso por SQL. Lo que cambia entre local y nube no es el acceso — siempre es cadena de conexión + SQL — sino dónde vive el almacén y quién administra el servidor.

7.1 En local: tu ordenador es el servidor

  1. El "servidor" es, literalmente, tu computador: el proceso postgres corre en tu máquina.
  2. El almacén es una carpeta de tu disco (la de la sección 2), que consume espacio de tu SSD como cualquier otra carpeta.
  3. No está siempre encendido: depende de cómo lo configures. Lo usual es encenderlo con un comando en consola (brew services start postgresql@17), que además lo deja auto-arrancando cada vez que inicias sesión; se apaga con brew services stop.
  4. La cadena de conexión apunta a tu propia máquina: localhost:5432.

7.2 En la nube: dos caminos (gestionado vs autogestionado)

En la nube la base ya no vive en tu máquina sino en un computador de un datacenter, encendido 24/7. La pregunta que separa los dos caminos es quién administra ese computador:

  1. Camino A — gestionado (managed), lo normal: Cloud SQL, RDS, Neon, Supabase. El proveedor corre el servidor Postgres por ti: lo instala, lo mantiene encendido, lo respalda y lo actualiza, con disco persistente garantizado. Tú nunca ves la máquina ni la carpeta del almacén — solo recibes una cadena de conexión y te conectas con SQL, igual que en local.
  2. Camino B — autogestionado (self-managed): alquilar una máquina virtual (Compute Engine, EC2) e instalar Postgres tú mismo. Es exactamente lo que hiciste en tu ordenador, pero en un computador remoto que nunca se apaga: instalas, enciendes el servicio, y el almacén es una carpeta del disco de esa máquina. El control es total — y la administración también es tuya: respaldos, actualizaciones, seguridad, y levantar la base cuando falle.

Para un analista o un proyecto pequeño, el camino gestionado es el default: pagas un poco más a cambio de no ser el administrador de la base.

8. Qué sigue

Ya sabes qué es PostgreSQL por dentro: un servidor que guarda tus bases en binario dentro de un almacén en disco, y al que todo — un script, DBeaver, Power BI — se conecta igual: cadena de conexión + SQL.

El siguiente paso es tenerlo corriendo en tu propia máquina. Eso es la parte 2 de esta serie: instalar PostgreSQL en Mac con Homebrew, arrancar el servidor y dar los primeros pasos con psql.

9. Gotchas

  • El Postgres nativo de Homebrew no tiene el usuario postgres ni una contraseña por defecto. Su superusuario es tu usuario de macOS (ej. angelgarciadatablog) y las conexiones locales suelen ser de confianza (sin contraseña). Si el código trae por defecto user: 'postgres', hay que sobreescribirlo con DB_USER=<tu-usuario-mac> — sin tocar el código, vía variable de entorno.
  • Arrancar el servicio no crea ninguna base. brew services start solo enciende el servidor. La base concreta hay que crearla aparte (createdb) y cargarle la estructura (.sql).
  • Las carpetas de una base de datos no se pueden copiar y pegar. Mover una base a otra máquina no es copiar su carpeta-número del almacén (sección 2): esos archivos solo funcionan dentro de su almacén original y con su versión exacta de Postgres. Para llevar los datos a otro lado siempre se exporta (sección 5.2): pg_dump para la base completa, COPY para sacar filas como CSV.
  • Una base "vacía" no pesa cero. Arranca en varios MB por el catálogo de sistema. Es normal.

10. Referencia oficial

  • Estructura física del almacenamiento: https://www.postgresql.org/docs/current/storage.html
  • pg_dump (respaldos): https://www.postgresql.org/docs/current/app-pgdump.html
  • COPY (exportar/importar CSV): https://www.postgresql.org/docs/current/sql-copy.html