La base de datos sobrevive a tu código. Un mal schema te persigue durante años. Uno bueno es invisible — simplemente funciona.
✅ user_orders ❌ UserOrder / userOrders ✅ id UUID DEFAULT gen_random_uuid() ❌ userId SERIAL ✅ user_id REFERENCES users(id) ❌ userId / user_fk ✅ created_at, updated_at ❌ created / lastUpdate ✅ CREATE INDEX idx_orders_user_id ON orders(user_id) ❌ user_id_idx / index1 ✅ is_active, has_subscription ❌ active, subscribed ✅ status TEXT CHECK (status IN (...)) ❌ ENUM type (difícil de migrar) UUID TEXT / VARCHAR(n) TIMESTAMPTZ NUMERIC / DECIMAL JSONB BOOLEAN Las migraciones son el historial clínico de tu base de datos. Si no podés recrear la DB desde cero con un comando, no tenés migraciones — tenés deuda.
Una query mal escrita puede tirar abajo producción. Las reglas no son muchas — pero violarlas es caro.
N+1 Queries SELECT * Missing index Query en loop Sin paginación Una transacción bien usada es una red de seguridad. Mal usada, es un cuello de botella que bloquea toda la aplicación.
READ COMMITTED REPEATABLE READ SERIALIZABLE