El 27 de noviembre de 2021, SQLite publicó la versión 3.37.0. No duplicaba el rendimiento, no traía funciones espectaculares. Solo permitía añadir una palabra al final de la sentencia CREATE TABLE: STRICT.
¿Qué significa? En lenguaje llano: a partir de ese día, SQLite por fin aprendió a rechazar algo —«poner un nombre en el campo del número de teléfono».
Por aquel entonces, habían pasado 21 años desde su nacimiento. Y es, precisamente, la base de datos invisible que usa cada aplicación de tu móvil.

El «cimiento» que no conoces en tu móvil
Antes que nada, hay que corregir un malentendido muy extendido: SQLite no es un «software» que puedas descargar de la tienda de aplicaciones. En tu móvil no hay ningún icono que se llame «SQLite». Es un motor de base de datos —se esconde dentro de las aplicaciones y se encarga silenciosamente de almacenar y gestionar los datos.
Los chats de WeChat, el historial de transacciones de Alipay, la caché de vídeos de Douyin, la agenda de contactos del móvil, las contraseñas guardadas en el navegador, los mapas sin conexión… detrás de todo eso está SQLite.
Según estimaciones fiables, hay más de un billón de bases de datos SQLite funcionando simultáneamente en el mundo. Ninguna otra base de datos se acerca siquiera a esa cifra. Es, sin discusión, «la número uno del mundo».
Pero esta campeona tiene una «habilidad» que cuesta creer: no comprueba en absoluto si el tipo de dato que almacenas es correcto.
«¿Edad? Pon “Juan”… Vale, dentro»
¿Qué significa «no comprobar el tipo de dato»? Pongamos un ejemplo de la vida real.
Vas a un banco a abrir una cuenta. El empleado te da un formulario. Hay una casilla para «edad» y otra para «nombre». Tú pones «Juan» en la edad y «42» en el nombre —en condiciones normales, el empleado te devolvería el formulario: «Señor, la edad tiene que ser un número y el nombre, texto.»
El comportamiento de SQLite en modo predeterminado equivale a que el empleado mire el formulario y diga, sin inmutarse: «Vale, tú pones lo que quieras y yo lo guardo. ¿Edad es “Juan”? Guardado. ¿Nombre es “42”? También. Es tu libertad.»
Traducido a código: creas una tabla, declaras que la columna «edad» almacena enteros (INTEGER) y la columna «nombre» almacena texto (TEXT). Luego ejecutas:
INSERT INTO Usuarios (edad) VALUES ('No soy un número');
En bases de datos como MySQL o PostgreSQL, esta sentencia da error al instante. ¿En SQLite? Se ejecuta sin problemas. Sin ninguna advertencia. Desde ese momento, en la columna «edad» de tu base de datos vive plácidamente un valor de texto llamado «No soy un número».
No es un caso extremo. El 11 de julio de 2026, el desarrollador Evan Hahn publicó un artículo titulado «Prefer STRICT tables in SQLite» (Prioriza las tablas STRICT en SQLite), que alcanzó casi 200 puntos y 89 comentarios en Hacker News. Los comentarios estaban llenos de desarrolladores compartiendo sus propias «historias de guerra» por haber caído en este mismo error.
Figura 1: Comparativa de comportamiento entre modo STRICT y modo no STRICT

| Operación | No STRICT (predeterminado) | Modo STRICT |
|---|---|---|
Escribir 'abc' en columna INTEGER (texto en columna numérica) | ✅ Acepta | ❌ Error |
Escribir '123' en columna INTEGER (texto numérico, convertible sin pérdida) | ✅ Acepta | ✅ Acepta |
Tipo de columna GARBAGE (error ortográfico / tipo ficticio) | ✅ Acepta | ❌ Error |
Escribir cualquier tipo en columna ANY | ✅ Acepta | ✅ Acepta |
| Crear tabla sin tipo de columna | ✅ Acepta | ❌ Error |
| Tipos permitidos | Sin límite | INT, INTEGER, REAL, TEXT, BLOB, ANY |
Una guerra filosófica de 20 años
Detrás de esto no hay descuido ni pereza. Es una decisión de diseño meditada por el creador de SQLite, D. Richard Hipp. El sitio web oficial de SQLite dedica una página entera titulada «The Advantages Of Flexible Typing» (Las ventajas de la tipificación flexible) a defender la decisión de no comprobar tipos.
Para entender el origen de esta decisión hay que remontarse al año 2000. Hipp trabajaba entonces para un contratista de la Armada estadounidense y necesitaba una base de datos ligera para los sistemas de un buque de guerra. Las opciones del mercado eran demasiado pesadas o necesitaban un servidor, algo totalmente inviable en el entorno de un barco. Así que se puso a escribir una.
Una influencia clave fue TCL, el lenguaje de programación que Hipp conocía mejor. TCL es un lenguaje de «tipado dinámico»: el programador no necesita declarar el tipo de una variable por adelantado; todo puede tratarse como una cadena de texto. Hipp trasladó esta filosofía a SQLite: ¿declaras el tipo de una columna? Bien, pero es solo una sugerencia. Lo que realmente almacenes, lo decides tú.
Durante los 20 años siguientes, el mundo de las bases de datos mantuvo un largo debate en torno a si la «tipificación flexible» era una característica o un error.
Los defensores (el propio Hipp y su equipo) esgrimen tres argumentos principales:
Primero: «Llevo 35 años programando y nunca he visto un error que la comprobación de tipos hubiera evitado.» Hipp escribe en la documentación oficial que, en sus décadas desarrollando TCL y SQLite, no recuerda ni un solo fallo causado por la falta de restricciones de tipo. Su conclusión es que la comprobación de tipos solo es útil en lenguajes de bajo nivel como C y C++, que trabajan cerca del hardware —en un motor SQL que trata todos los datos como «objetos valor», la comprobación de tipos no ayuda gran cosa.
Segundo: «La comprobación de tipos solodetiene errores burdos y fáciles de encontrar.» Este argumento es bastante afilado: meter «nombre» en el campo «edad» es un disparate que cualquier prueba unitaria detecta al instante. Lo que realmente te hace perder tres días depurando es poner el apellido donde va el nombre —ambos son texto, y la comprobación de tipos no lo ve. Hipp cree que la comprobación de tipos da al desarrollador una falsa sensación de seguridad de que «los datos ya están limpios».
Tercero: «La flexibilidad te permite hacer cosas que otras bases de datos no pueden.» Por ejemplo, usar una misma tabla como almacén clave-valor de cualquier tipo, reutilizar columnas obsoletas para múltiples propósitos, o importar directamente archivos CSV sucios exportados de Excel para limpiarlos después.
Los detractores contraatacan con la misma contundencia:
«Precisamente esos errores “burdos” se convierten en la aguja que no encuentras en un pajar de millones de filas. La comprobación de tipos no está pensada para evitar el error que pillas depurando —está pensada para evitar ese momento a las tres de la madrugada en producción, cuando el registro no muestra ningún error pero los datos del usuario ya están completamente corruptos.»
«Dices que llevas 35 años programando y no has visto un error de tipos? SQLite está escrito en C. Cuando lo compilas, estás disfrutando de la comprobación de tipos de C. Te apoyas en un sistema de tipos estricto para que SQLite no tenga fallos, ¿y me dices que la comprobación de tipos no es importante para los demás?»
En los comentarios de Hacker News, una analogía se repite constantemente: «Es como usar UDP en lugar de TCP —sacrificas la verificación de datos por velocidad y simplicidad, y luego te toca implementar manualmente la retransmisión, el ordenamiento y la validación a nivel de aplicación. Cuando terminas, te das cuenta de que solo has implementado un TCP peor.»
Otro comentarista fue más directo: «Ajustar los valores predeterminados por rendimiento es aceptable. Ajustarlos por corrección —da desconfianza.»
¿Qué hace exactamente el modo STRICT?
Volvamos a noviembre de 2021. La palabra clave STRICT hace tres cosas, resumidas:
1. Rechazar escrituras con tipos incorrectos. ¿Meter texto en una columna de enteros? Error. ¿Meter un número en una columna de texto? Se acepta —porque un número se puede convertir a texto sin pérdida. ¿Meter la cadena '123' en una columna de enteros? También se acepta —porque '123' se puede convertir perfectamente al número 123. STRICT comprueba si «el valor se puede convertir sin pérdida», no solo el tipo superficial. En esto, es más inteligente que muchas bases de datos de tipado estricto.
2. Rechazar tipos de datos ficticios. En modo no STRICT, si al crear la tabla escribes GARBAGE, DATETIME, JSON, UUID o BLOBB como tipo de columna, SQLite lo acepta sin rechistar, tratándolo como un tipo genérico. En modo STRICT, solo reconoce seis: INT, INTEGER, REAL, TEXT, BLOB y ANY. Si tecleas BLOBB en lugar de BLOB, te lo señala al instante.
3. Cuando necesitas flexibilidad, usa ANY. STRICT no es un corte radical. Si declaras una columna como tipo ANY, acepta cualquier tipo de dato —tan libre como el modo predeterminado. La diferencia: la flexibilidad la decides tú, no está activada por defecto en todas partes.
¿Por qué esperaron 21 años?
Del año 2000 a 2021, 21 años. ¿Por qué un mecanismo de verificación tan básico tardó toda la carrera profesional de dos generaciones de ingenieros en llegar?
La respuesta está en el compromiso central de SQLite: la retrocompatibilidad.
Los desarrolladores de SQLite tienen una regla de hierro casi obsesiva: el código SQLite que escribes hoy debe funcionar al 100 % dentro de diez años, incluso después de actualizar la versión. Esto significa que el comportamiento predeterminado nunca puede cambiar. Si cambiara, podría afectar a los billones de instancias de SQLite en funcionamiento en todo el planeta.
Figura 2: Cronología de la evolución de la seguridad de tipos en SQLite
2000 ─ Lanzamiento de SQLite 1.0, tipificación flexible como filosofía central
│
│ "El tipo de columna es una sugerencia, no una restricción"
│
2009 ─ SQLite 3.6.19: soporte sintáctico de claves foráneas
│ Pero desactivado por defecto, requiere PRAGMA foreign_keys = ON manual
│
│ Durante los 12 años siguientes, la propuesta del modo STRICT
│ se discute repetidamente, pero la regla de retrocompatibilidad
│ la mantiene fuera
│
2021 ─ SQLite 3.37.0: soporte de tablas STRICT
│ Añadir STRICT al final de CREATE TABLE, activación por tabla
│ Sin interruptor global —sigue siendo la filosofía de "tú eliges"
│
2026 ─ Evan Hahn publica: "Prioriza las tablas STRICT"
│ 199 puntos, 89 comentarios en HN, el debate continúa
Tres hitos a lo largo de 21 años, cada uno siguiendo el mismo principio: se pueden añadir funciones, pero no se puede cambiar el comportamiento predeterminado.
No es un caso aislado. Las claves foráneas —que evitan que borres un usuario y dejes diez mil pedidos «huérfanos» en la tabla de pedidos— SQLite ya soportaba su sintaxis en 2009, pero siguen desactivadas por defecto. Cada vez que abres una conexión a la base de datos, tienes que ejecutar manualmente:
PRAGMA foreign_keys = ON;
para activar la comprobación de claves foráneas. La razón es idéntica: cambiar el valor predeterminado rompería la retrocompatibilidad.
En la sección de comentarios de HN, alguien propuso una solución intermedia: como hacen los navegadores, declarar COMPAT_MODE=2026 al crear la base de datos, y que la nueva versión active automáticamente la configuración recomendada de la época. Pero la propuesta no se ha adoptado hasta la fecha.
Un comentarista escribió: «SQLite cambia muy, muy pocas veces los valores predeterminados porque su compromiso con la retrocompatibilidad es casi sagrado. No quieren que un desarrollador que escribió su software para SQLite 3.53 vea cómo, al actualizar a la 3.54, todo explota porque CREATE TABLE de repente se ha vuelto STRICT.»
Esta frase resume perfectamente el dilema de SQLite: por un lado, el impulso evolutivo de «ser cada vez mejor»; por otro, el juramento de compatibilidad de «no cambiar nunca».
El éxito de SQLite radica precisamente en que no controla nada
Llegados a este punto, surge una pregunta contraintuitiva: si SQLite tiene tantos diseños «no seguros por defecto», ¿por qué es la base de datos más popular del mundo?
La respuesta está en su filosofía de diseño. El éxito de SQLite se debe en gran medida a su «no controlar nada».
No necesita instalación, no necesita servidor, no necesita archivos de configuración. Un archivo de biblioteca de unos pocos cientos de KB se incrusta en la aplicación y ya funciona. No controla los tipos de datos —almacena lo que quieras. No controla las relaciones de claves foráneas —si pasa algo, es tu problema. No controla el nivel de aislamiento de las transacciones —primero, que funcione.
La recompensa de este minimalismo es: metes SQLite en un móvil, un navegador, un sensor IoT, un router, una smart TV, un sistema de infoentretenimiento de coche, un sistema de entretenimiento de avión —nunca se queja del entorno, nunca exige recursos, nunca falla al arrancar.
Es como un enchufe universal: valen todo tipo de clavijas. Si hay cortocircuito, no es problema mío.
La llegada del modo STRICT significa que esta base de datos que «no controlaba nada» durante 21 años ha reconocido una realidad: cuando tus usuarios pasan de ser unas docenas de programadores profesionales de C a millones de desarrolladores de aplicaciones con niveles muy dispares, la «libertad» por defecto se está convirtiendo en «riesgo» por defecto.
Epílogo
Esta historia de SQLite, vista en el gran esquema de la ingeniería del software, es el reflejo de toda una industria que va madurando.
El software primitivo se dirigía a unos pocos usuarios profesionales, con la filosofía de «te doy la máxima libertad; si algo sale mal, es tu problema». El software actual se dirige a miles de millones de personas corrientes, y el centro de gravedad del diseño se ha desplazado de la «libertad» a la «seguridad» y «a prueba de tontos».
El modo STRICT no es un avance técnico emocionante —lo que hace, MySQL y PostgreSQL lo sabían hacer desde el primer día. Pero el hecho de que llegara con 21 años de retraso dice en silencio algo importante: muchas de las «funciones básicas» que hoy damos por sentadas se han conseguido con décadas de acumulación en la industria, debates, errores y retrospectivas —poco a poco.
La próxima vez que tu aplicación de móvil guarde datos silenciosamente en SQLite, piensa en esto: este campeón invisible que ha estado funcionando en tu teléfono durante miles de días y noches, en su año 21 de vida, por fin aprendió una habilidad que un niño de jardín de infancia ya domina —
no meter los zapatos en el cuenco de la comida.
Enlaces de referencia: