Mis notas sobre el diseño del esquema Postgres de GitLab (2022)

Las decisiones de esquema PostgreSQL de GitLab provocan una crítica amplia sobre cómo las aplicaciones modernas modelan datos a escala. Los comentaristas examinan los compromisos entre claves primarias de 32 y 64 bits, UUIDs frente a IDs secuenciales, y estrategias de migración de esquema en línea, destacando cómo la localidad de índice, las claves foráneas y las abstracciones de ORM pueden hacer o deshacer el rendimiento en tablas con miles de millones de filas. El hilo también cuestiona “mejores prácticas” comunes como ocultar las claves primarias a los usuarios, argumentando que a menudo reflejan preocupaciones empresariales y competitivas más que seguridad, y enfatizando que un diseño cuidadoso, centrado en la base de datos, sigue siendo crucial pese a los avances en herramientas.

Tamaño de la clave primaria, migraciones y herramientas

  • Muchos comentarios debaten entre PKs int y bigint. Algunos sostienen que alcanzar los límites de 32 bits es un riesgo real para servicios grandes y “demasiado cerca para estar tranquilos”, mientras que otros señalan que los datos reales (por ejemplo, repositorios/issues de GitHub) siguen por debajo de 2^31.
  • Se describe que migrar de int→bigint es factible pero no trivial a escala: reescrituras de tablas, reconstrucción de índices, claves foráneas y la creación de índices en un solo hilo pueden llevar horas en tablas de varios TB.
  • Se mencionan enfoques de cero/bajo tiempo de inactividad: replicación lógica con switchover, herramientas de cambio de esquema en línea (pg-osc, gh-ost), desacoplar las migraciones de esquema de los despliegues de la app, y sistemas de migración operados por DBAs.
  • Algunos señalan dolor adicional: deserialización de bigint en JavaScript, consumidores posteriores que asumen ints de 32 bits.

UUIDs frente a enteros secuenciales

  • Se critica UUIDv4 como PK principalmente por rendimiento, no por tamaño. 8 bytes extra por entrada de FK/índice se acumulan en muchas tablas y hacen más difícil que los índices quepan en RAM.
  • Los UUID aleatorios destruyen la localidad del índice: las inserciones btree quedan dispersas, causan bloat de páginas y provocan fuertes caídas de rendimiento cuando los índices superan la memoria, no solo una penalización estable de ~25%.
  • Se discuten IDs ordenados por tiempo (UUIDv6/v7, estilo Snowflake, secuencias cifradas o permutadas) como mejores compromisos, pero con trade-offs (filtración de tiempo, rotación de claves, complejidad).

Diseño de esquema, ORMs y migraciones

  • Varios argumentan que el diseño de esquemas es “de la edad de piedra” y que las herramientas de migración (EF, Rails, Django, Prisma, etc.) o bien generan migraciones peligrosas (bloqueos, reescrituras) o bien ocultan lo que realmente se ejecuta.
  • Hay una fuerte corriente a favor de pensar primero en el esquema y usar SQL simple (a menudo con procedimientos almacenados) en lugar de ORMs pesados, que se consideran propensos a filtraciones, complejos y difíciles de operar a escala.
  • Otros defienden los ORMs como útiles para consultas dinámicas y grafos de objetos complejos, si se usan con comprensión.

Arquitectura y rendimiento de GitLab frente a GitHub

  • Algunos perciben que las páginas de GitLab son notablemente más lentas que las de GitHub. Las explicaciones ofrecidas incluyen la cultura y la priorización del rendimiento, pero los detalles son anecdóticos e incompletos.
  • Hay desacuerdo/incertidumbre sobre si GitLab.com es una sola base de datos multi-tenant o una base de datos por cliente; un comentario afirma que esencialmente es una instancia multi-tenant de su producto autohospedado.

Exponer claves primarias y “external IDs”

  • Un sector ve ocultar PKs secuenciales como mayormente “teatro de seguridad”; si la autorización está rota, los IDs adivinados no deberían importar.
  • Otros enfatizan la defensa en profundidad y la inteligencia competitiva: los IDs secuenciales revelan conteos/crecimiento (pedidos, usuarios, issues) y facilitan la enumeración masiva y la explotación.
  • Los ejemplos incluyen volúmenes de pedidos en e-commerce, enumeración de usuarios y scraping; los contraargumentos afirman que los atacantes motivados a menudo pueden inferir datos similares de todos modos.
  • El id interno al estilo GitLab más un iid por proyecto se ve como algo más amigable para el usuario y desacopla las URLs de los cambios en el PK interno, a costa de joins e índices adicionales.

Detalles específicos de Postgres: text frente a varchar, FKs

  • La discusión aclara que en Postgres, text frente a varchar(n) no tiene diferencia de rendimiento en tiempo de ejecución; el problema real es el coste de migración al cambiar longitudes en varchar(n) frente a ajustar un CHECK sobre text.
  • Un comentarista rebate la idea de que las claves foráneas sean “caras”, argumentando que la integridad debe imponerse en algún lugar y que las FKs a nivel de base de datos suelen ganar si se usan correctamente.