Neon vs Docker
Los dos entornos de base de datos de ixiclinic — Neon Serverless en desarrollo, PostgreSQL 17 en Docker en producción — y por qué el esquema debe aplicarse a ambos.
ixiclinic opera con dos bases de datos PostgreSQL distintas según el entorno. Son independientes y hay que mantenerlas alineadas.
| Desarrollo | Producción | |
|---|---|---|
| Motor | Neon Serverless PostgreSQL | PostgreSQL 17 (imagen postgres:17-alpine) |
| Dónde corre | Nube (Neon) | Contenedor Docker en el VPS |
| Conexión | URL de Neon con sslmode=require | Red interna de Docker (postgres:5432) |
| Cómo se migra | pnpm db:migrate / pnpm db:push | Automático al arrancar el contenedor del API |
Desarrollo — Neon Serverless
En desarrollo cada quien apunta DATABASE_URL (en apps/api/.env.local) a una base Neon
Serverless PostgreSQL. Es PostgreSQL gestionado, sin servidor que mantener, ideal para
iterar localmente.
El cliente de apps/api/src/db/index.ts detecta Neon por la cadena de conexión y activa SSL
automáticamente:
const client = postgres(env.DATABASE_URL, {
ssl: env.DATABASE_URL.includes('sslmode=require') ? 'require' : undefined,
});Los cambios de esquema se aplican con los comandos db:* desde apps/api
(ver Drizzle ORM).
Producción — PostgreSQL 17 en Docker
En producción PostgreSQL corre como un contenedor Docker en el VPS, definido en
apps/api/deploy/docker-compose.prod.yml (imagen postgres:17-alpine). El API y la base
comparten una red Docker interna, así que el API se conecta por el nombre de servicio
(postgres:5432) y la base no se expone a internet.
El nombre de base, usuario y contraseña se inyectan por variables de entorno (DB_NAME,
DB_USER, DB_PASSWORD) desde un archivo de entorno que no se commitea. Ver
Despliegue.
Las migraciones se aplican solas al levantar el contenedor del API (ver Migraciones).
Por qué importa aplicar a ambas
Como son dos bases físicas distintas, un cambio de esquema solo existe donde lo hayas aplicado:
- En desarrollo lo aplicas tú con
pnpm db:migrate(odb:push). - En producción llega al desplegar, porque el contenedor corre
migrate.jsal arrancar.
Nota: si una migración funciona en desarrollo pero el
.sqlarrastra drift, puede fallar en producción y, como el API falla rápido, el contenedor no levantará. Revisa siempre el SQL generado antes de desplegar.
Migraciones
Flujo generate → migrate de Drizzle, la migración automática en el arranque de producción, la función NCF de numeración fiscal, el riesgo de drift y la regla de aplicar todo cambio a ambas bases.
Dominios del esquema
Recorrido por los 25 archivos de apps/api/src/db/schema, con las tablas clave de cada dominio y los detalles de catalog, billing, saas y tenants.