# Compañeros para PostgreSQL



## Compañeros del ecosistema de PostgreSQL: pgAdmin, PgBouncer y pruebas de rendimiento

Ejecutar un contenedor PostgreSQL independiente a menudo es solo el comienzo. ¿Qué sucede cuando llegan miles de conexiones o cuando necesitas una interfaz visual para administrar tu base de datos?

Aquí es donde entran en juego las **herramientas de soporte (companion tools)**. Estas aplicaciones extienden PostgreSQL con capacidades que el motor de base de datos principal no proporciona de forma nativa: administración visual, agrupación de conexiones (connection pooling) y evaluación de rendimiento. Esta guía cubre cómo desplegar pgAdmin 4, PgBouncer, Pgpool-II y `pgbench` en Docker, cuándo usar cada herramienta y los resultados de evaluaciones de rendimiento en el mundo real que demuestran su impacto.

## pgAdmin 4: Plataforma de administración visual

pgAdmin 4 es la herramienta de administración de código abierto estándar de la industria para PostgreSQL. Cuando se despliega en Docker, normalmente se ejecuta en **Modo Servidor**, proporcionando una interfaz web multiusuario para administrar una o más instancias de base de datos.

Aunque puedes hacer todo desde la línea de comandos usando `psql`, una interfaz visual simplifica significativamente la escritura de consultas complejas, la visualización de estructuras de tablas y la exploración de objetos de base de datos.

### Consideraciones clave

Al ejecutar pgAdmin en Docker, ten en cuenta estos puntos:

- **Imagen**: Usa la imagen oficial `dpage/pgadmin4`.
- **Red**: En un entorno de Docker Compose, pgAdmin se conecta a la base de datos utilizando el nombre del servicio interno (por ejemplo, `db:5432`) en lugar de `localhost`.

### Configuración de Docker Compose

Para desplegar rápidamente pgAdmin:

```yaml
pgadmin:
  image: dpage/pgadmin4:8.14
  environment:
    PGADMIN_DEFAULT_EMAIL: admin@example.com
    PGADMIN_DEFAULT_PASSWORD: secure_password
  volumes:
    - pgadmin_data:/var/lib/pgadmin
  ports:
    - "8080:80"
```

Con esta configuración, accede a la interfaz de pgAdmin en `http://localhost:8080`. Usa el correo electrónico y la contraseña especificados en las variables de entorno para el inicio de sesión inicial.

> [!IMPORTANT]
>
> En entornos de producción, pasa `PGADMIN_DEFAULT_PASSWORD` como una variable de entorno externa o utiliza secretos de Docker. Almacenar contraseñas en texto plano dentro de `docker-compose.yml` representa un riesgo de seguridad.

Ahora que tienes configurada la administración visual de la base de datos, el siguiente desafío en entornos de producción es manejar la carga de conexiones. La siguiente sección explica cómo gestionar el tráfico de base de datos de gran volumen.

## PgBouncer: Agrupación de conexiones ligera

PostgreSQL crea un nuevo proceso para cada conexión de cliente, lo que consume una cantidad significativa de RAM. ¿Qué sucede cuando tienes 1,000 usuarios concurrentes? PgBouncer resuelve exactamente este problema.

PgBouncer es un proxy ligero que agrupa conexiones, lo que permite que miles de aplicaciones compartan un pequeño número de backends reales de base de datos. Piénsalo como un controlador de tráfico: todos quieren pasar simultáneamente, pero el controlador regula el flujo para evitar la congestión.

### Modos de agrupación (pooling)

PgBouncer ofrece tres modos de agrupación diferentes:

| Modo | Descripción | Caso de uso |
|------|-------------|----------|
| **Sesión** | Conexión asignada durante toda la duración de la sesión | Conexiones de larga duración, variables de sesión |
| **Transacción** | Conexión devuelta después de que termina cada transacción | Aplicaciones web, microservicios (lo más común) |
| **Sentencia** | Conexión devuelta después de cada sentencia SQL | Consultas simples, sin transacciones de múltiples sentencias |

### Cuándo usar PgBouncer

PgBouncer se vuelve esencial cuando te encuentras con:

- Errores de "too many connections" (demasiadas conexiones)
- Alto consumo de memoria debido a la sobrecarga de conexiones
- Muchas conexiones de corta duración (aplicaciones web, funciones serverless)
- Necesidad de atender a miles de clientes con conexiones de base de datos limitadas

### Configuración completa de Docker Compose

Para ejecutar PostgreSQL y PgBouncer juntos, necesitas tres archivos: `docker-compose.yml`, `pgbouncer.ini` y `userlist.txt`.

Primero, crea el archivo de configuración de PgBouncer (`pgbouncer.ini`):

```bash
[databases]
benchmark = host=postgres port=5432 dbname=benchmark user=postgres

[pgbouncer]
listen_addr = 0.0.0.0
listen_port = 6432
auth_type = trust
auth_file = /etc/pgbouncer/userlist.txt
admin_users = postgres
pool_mode = transaction
max_client_conn = 1000
default_pool_size = 50
min_pool_size = 10
reserve_pool_size = 10
max_db_connections = 100
```

A continuación, crea el archivo de autenticación de usuarios (`userlist.txt`):

```bash
"postgres" "postgres"
```

Finalmente, crea el archivo de Docker Compose (`docker-compose.yml`):

```yaml
services:
  postgres:
    image: postgres:18
    container_name: postgres
    environment:
      POSTGRES_USER: postgres
      POSTGRES_PASSWORD: postgres
      POSTGRES_DB: benchmark
      POSTGRES_HOST_AUTH_METHOD: trust
    volumes:
      - postgres_data:/var/lib/postgresql
    ports:
      - "5432:5432"
    networks:
      - pgnet
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

  pgbouncer:
    image: percona/percona-pgbouncer:1.25.0
    container_name: pgbouncer
    volumes:
      - ./pgbouncer.ini:/etc/pgbouncer/pgbouncer.ini
      - ./userlist.txt:/etc/pgbouncer/userlist.txt
    ports:
      - "6432:6432"
    networks:
      - pgnet
    depends_on:
      postgres:
        condition: service_healthy

volumes:
  postgres_data:

networks:
  pgnet:
    driver: bridge
```

Notas clave sobre la configuración:

- `PgBouncer` escucha en el puerto **6432**, evitando confusiones con la conexión directa de PostgreSQL en el puerto 5432.
- La directiva `depends_on` con la condición `service_healthy` garantiza que PgBouncer se inicie solo después de que PostgreSQL esté listo.
- `pool_mode = transaction` es la opción óptima para la mayoría de las aplicaciones web.
- La [imagen Percona PgBouncer](https://hub.docker.com/r/percona/percona-pgbouncer) requiere archivos de configuración montados (sin la bandera `:ro`, ya que el script del punto de entrada necesita modificarlos).
- Este ejemplo utiliza autenticación `trust` por simplicidad. En producción, configura una autenticación SCRAM-SHA-256 adecuada.

> [!NOTE]
>
> El script del punto de entrada de `Percona PgBouncer` procesa los archivos de configuración al iniciar. Móntalos sin la bandera de solo lectura para evitar errores de permisos.




## `pgbench`: Evaluación de rendimiento (benchmarking)

`pgbench` es una utilidad de benchmarking incluida con la imagen oficial de PostgreSQL. Te permite simular cargas de trabajo pesadas y verificar cómo se comporta tu configuración de Docker bajo presión.

### Inicializar tablas de benchmark

Primero, crea las tablas de prueba. El parámetro `-s` (escala) determina el tamaño de los datos; un factor de escala de 50 crea aproximadamente 5 millones de filas:

```bash
docker exec postgres pgbench -i -s 50 -U postgres benchmark
```

### Ejecutar pruebas de estrés

Parámetros clave:

- `-c`: Número de clientes simulados
- `-j`: Número de hilos (threads)
- `-T`: Duración en segundos

Prueba con conexión directa a PostgreSQL:

```bash
docker exec postgres pgbench -h localhost -U postgres -c 50 -j 4 -T 60 benchmark
```

Prueba a través de PgBouncer:

```bash
docker exec postgres pgbench -h pgbouncer -p 6432 -U postgres -c 50 -j 4 -T 60 benchmark
```

## Comprender los resultados del benchmark

¿Realmente marca la diferencia PgBouncer? Ejecuta las pruebas tú mismo para descubrirlo. Tus resultados varían según tu hardware, configuración de Docker, configuración de red y carga del sistema.

### Qué esperar

Cuando ejecutes estas pruebas de rendimiento, observarás patrones en lugar de números específicos. Piénsalo como comparar dos rutas diferentes para ir al trabajo: la ruta "más rápida" depende de las condiciones del tráfico, la hora del día y tu vehículo.

### Observaciones clave

Al comparar conexiones directas con PgBouncer, normalmente notarás lo siguiente:

#### 1. La sobrecarga de conexión difiere significativamente

Las conexiones directas requieren que PostgreSQL genere un nuevo proceso para cada cliente. PgBouncer reutiliza las conexiones existentes. Observa la métrica "initial connection time" (tiempo de conexión inicial) en tus resultados: PgBouncer a menudo muestra una configuración de conexión drásticamente más rápida.

#### 2. El comportamiento bajo presión revela la verdadera diferencia

Intenta aumentar el número de clientes (parámetro `-c`) gradualmente: 50, 100, 150, 200. En algún momento, las conexiones directas fallarán con un error de "too many clients already" (demasiados clientes), mientras que PgBouncer continuará procesando las solicitudes. Este es el valor principal de PgBouncer: **evita el agotamiento de conexiones**.

#### 3. El rendimiento (throughput) varía según el entorno

En algunos sistemas, las conexiones directas muestran transacciones por segundo (TPS) más altas con baja concurrencia. En otros, PgBouncer gana incluso con pocos clientes. La diferencia depende de:
- CPU y memoria disponibles
- Sobrecarga de red de Docker
- Velocidad de E/S de disco
- Si las conexiones se abren y cierran rápidamente

