https://a.storyblok.com/f/270183/1368x665/9c72c5f61f/25jun_dev-blog_sqlite.jpg

El regreso de SQLite

Publicado el June 12, 2025

Tiempo de lectura: 13 minutos

Introducción

Vale, lo admito: no es un regreso. Llamémoslo más bien una reimaginación. SQLite existe desde el año 2000, y su uso original era el seguimiento de misiles a bordo de destructores de la Marina de los Estados Unidos. Sin duda ha demostrado sus credenciales como sistema de base de datos relacional, aunque en los últimos 10 años hemos asistido al auge de los sistemas de bases de datos NoSQL orientados a documentos, que quizá le hayan quitado algo de protagonismo. En este artículo, voy a explorar el potencial de SQLite y demostrar lo rápido que es ponerlo en marcha con una arquitectura de producción en mente. Vale, lo admito; no es una vuelta atrás. Digamos que es más bien una reimaginación. SQLite existe desde el año 2000. Aunque la última década ha visto el auge de las bases de datos NoSQL y orientadas a documentos, que han acaparado gran parte de la atención, SQLite sigue siendo una opción potente. Desarrollada originalmente para el seguimiento de misiles en los destructores de la Marina de los Estados Unidos, ha demostrado silenciosamente ser una base de datos relacional fiable. Lo más probable es que estés pasando por alto su potencial en una arquitectura de producción. En este artículo, te mostraré lo rápido y fácil que es poner en marcha SQLite.

>> TL;DR: Puede encontrar el código fuente completo en GitHub.

¿Se puede utilizar SQLite en producción?

Vaya introducción, pero ¿qué es lo que los ingenieros de software, y en concreto los desarrolladores de aplicaciones web, conocen por SQlite? Bueno, principalmente tiene dos reputaciones:

  • Necesito ejecutar mis pruebas y no quiero hacer girar un completo Postgres ¿por qué no usar este pequeño archivo útil para ejecutarlo?

  • Es para sistemas embebidos porque es pequeño, ¿no? Pero eso no sirve para mi aplicación web, que generará montañas de datos.

No hay discusión con el punto número uno: SQLite es increíblemente útil para las pruebas. Tienes, digamos, tu arquitectura existente en código: migraciones, sembradores y similares. Así que, cuando ejecutes tu conjunto de pruebas, en lugar de usar un servidor de base de datos compatible con SQL, como MySQL, MariaDBo Postgres, ejecutas el mismo código pero con un archivo SQLite en blanco. Perfecto. ¿Pero qué pasa con el punto 2?

Ventajas de SQLite: Portabilidad

Dark brown vintage leather briefcase with metal buckles, resting on a round wooden stool against a white backgroundJust one file: portability at its finestSí, es pequeño. Mejor aún, la conectividad es sencilla: es solo un archivo.

Hay toda una serie de plugins IDE y compatibilidad - los IDE de Jetbrains tienen un panel de base de datos que puede crear un nuevo archivo SQLite, y VSCode tiene un montón de plugins para manejar esto por ti. Es decir, para los desarrolladores desarrolladores, puedes crearlo directamente desde Vim.

La huella fuera de la caja es de apenas 699kb. Eso es todo. Sin servicios que ejecutar, sin procesos en segundo plano, sólo un archivo.

Esto es muy diferente a los recursos necesarios para poner en marcha un servidor MySQL completo.

Ahora, llegamos a la pregunta que la mayoría de la gente quiere hacerse: si es tan sencillo, ¿por qué no utilizamos SQLite en más aplicaciones web?

La respuesta suele reducirse a suposiciones. Las bases de datos relacionales basadas en servidores dominan, pero con un poco de consideración, puede que te des cuenta de que SQLite se ajusta perfectamente a nuestros requisitos reales.

Ventajas de SQLite: Rendimiento

La velocidad de lectura y escritura es una de las mayores diferencias. SQLite, para una base de datos mediana de un par de millones de filas, es increíblemente rápida. Las pruebas de rendimiento varían, pero las consultas en solitario tardan hasta 5 ms, en comparación con una media máxima de unos 10 ms para MySQL.

Sin embargo, si SQLite lo matara en todos los benchmarks, claramente lo estaríamos usando para todo cuando no es tan frecuente en el desarrollo de aplicaciones web. En primer lugar, la velocidad de escritura es mucho más lenta. SQLite puede escribir aproximadamente hasta 300 inserciones en un solo hilo, comparado con hasta 50k en MySQL (dependiendo del entorno). Es una gran diferencia.

Lo segundo que hay que tener en cuenta es que SQLite tiene un mecanismo de bloqueo de un solo hilo; los registros que se están leyendo o escribiendo/actualizando tienen cinco estados de escritura posibles. Al escribir, el estado de bloqueo de un registro cambia a EXCLUSIVE, lo que restringe cualquier otra acción concurrente. MySQL, sin embargo, utiliza MVCC, o Multi-Version Concurrency control, que permitirá muchas lecturas y escrituras concurrentes.

Casos prácticos

Una de las preguntas que intento recordar constantemente a la gente es ¿Cuál es tu caso de uso? En el mundo de la nube nativa y Kubernetes, muchos argumentan que "PHP es lento" porque "Node tiene un bucle de eventos", pero lo que insto a la gente a pensar es "¿qué va a hacer tu aplicación de forma realista? de forma realista hacer? Si vas a estar almacenando algunos datos de usuario o subiendo algunos CSVs e imágenes, ¿estás realmente ¿realmente vas a ver la diferencia entre la elección del lenguaje y el framework? En muchos casos, probablemente no. Lo mismo ocurre con SQLite frente a MySQL: SQLite sigue siendo una opción fantástica si tienes algunos datos, pero lo más importante, ¿vas a tener 20.000 usuarios escribiendo en la base de datos de tu aplicación? Si estás escribiendo la próxima iteración de una aplicación de taxi global, entonces seguro. Lo que quiero decir es que SQLite es mucho más adecuado para muchos casos de desarrollo de lo que muchos creen.

Configuración del proyecto

Requisitos previos

Vonage API Account

To complete this tutorial, you will need a Vonage API account. If you don’t have one already, you can sign up today and start building with free credit. Once you have an account, you can find your API Key and API Secret at the top of the Vonage API Dashboard.

Basta de charla, es hora de mostrar las pocas líneas de código que podemos escribir para demostrar una escritura SQLite a nivel de producción con Typescript. Vamos a exponer una aplicación que podrá leer webhooks generados por la Mensajes API de Vonage. En primer lugar, crea un nuevo directorio para tu proyecto, navega dentro de él, y crea un nuevo proyecto Node.

npm init --yes

Esto utilizará los valores por defecto para su package.json que se ha creado. A continuación, tenemos que instalar TypeScript:

npm install typescript
npx tsc --init

Typescript se compila en JavaScript plano y utiliza un archivo de configuración tsconfig.json, que se crea durante la instalación. Abra este archivo de configuración y sustituya la plantilla por lo siguiente:

{
 "compilerOptions": {
   "target": "es2016",
   "module": "CommonJS",
   "rootDir": "./",
   "outDir": "./dist",
   "esModuleInterop": true,
   "forceConsistentCasingInFileNames": true,
   "strict": true,
   "skipLibCheck": true,
   "moduleResolution": "node",
   "baseUrl": ".",
   "paths": {
     "@prisma/client":["node_modules/@prisma/client"]
   }
 },
 "include": ["src/**/*.ts"]
}

Las partes importantes de esta configuración a tener en cuenta son:

  • TypeScript compilará en un directorio que se creará si no existe, llamado dist. Este será el punto de entrada a su aplicación.

  • Verá que Prisma está en la paths clave. Esto es porque, cuando instalamos Prisma, también necesita ser compilado (en cierto modo). Cuando definimos modelos dentro de Prisma, se utiliza un comando de generación para crear un cliente Prisma a medida.

Tenemos seis dependencias:

  • Prisma: nuestro mapeador relacional de objetos

  • ts-node: nos permite ejecutar TypeScript sin compilar en el directorio de salida

  • nodemon: para nuestro servidor de desarrollo, el código se recarga cuando se modifica

  • dotenv: para la gestión de variables de entorno)

  • Express: nuestro router

  • Sqlitepara nuestra conexión a la base de datos

Puede instalarlos todos de una sola vez en la línea de comandos:

npm install prisma ts-node nodemon dotenv express @types/express sqlite3

Prisma es un ORM que puede manejar tus modelos de datos, migraciones y todas las demás consultas. Para configurar su directorio Prisma, tenemos que ejecutar el comando init para ello:

npx prisma init --datasource-provider sqlite --output ../generated/prisma

Este comando configurará Prisma para que genere una clase Cliente compilada en el directorio ../generado/prisma y le indica que SQLite es nuestra fuente de base de datos. Al ejecutar este comando, Prisma le preguntará por cualquier dependencia adicional requerida, y luego configura su archivo .env . Configuraremos este archivo más tarde.

Configuración de una base de datos en WebStorm

Como SQLite es un archivo manejado por una librería, puedes crearlo con la mayoría de los IDEs modernos que tienen soporte para controladores. Ahora abre tu proyecto en Webstorm. A continuación, haga clic en el icono de base de datos en el panel de la derecha. A continuación, haga clic en el botón "+" para crear una nueva base de datos. Selecciona Data Source y desplázate hacia abajo hasta que veas SQLite. Esto te da tu modal para crear una nueva base de datos:

Screenshot of generating a new database connection in WebstormJetbrains Supports A Massive List of DBsElija SQLite como tipo y aparecerá la ventana emergente de creación:

Screenshot of SQlite database creation in WebstormCreate Your DatabaseLa primera vez que haga esto, si no ha usado WebStorm antes, el IDE detectará que no tiene los drivers SQlite instalados como una advertencia renderizada en el lugar donde está la opción Test Connection opción. Si no tiene los controladores, haga clic en el enlace para instalarlos.

En el campo Name campo, cambie identifier.sqlite a webhooksy el nombre del archivo a webhooks.sqlite. Usted quiere que el archivo se encuentra en la raíz del proyecto, así que pulse los puntos a la derecha del campo de archivo para asegurarse de que la ubicación es correcta. A continuación, haga clic en Aceptar.

Su cliente Prisma está configurado en prisma/schema.prismapero extrae la var DATABASE_URL env var de su archivo .env archivo. Abra su archivo envy reemplázalo así

DATABASE_URL="file:../webhooks.sqlite"

Prisma está configurado para generar el cliente ORM a medida en el directorio node_modules directorio. No queremos que se genere en el directorio @prisma así que en el archivo schema.prisma reemplaza la configuración del cliente así, debajo de la fuente de datos:

generator client {
 provider = "prisma-client-js"
 output   = "../node_modules/.prisma/client"
}

Lo que esto hace es decirle a Prisma que ponga el cliente generado en un nuevo directorio, .prisma. Más adelante, al crear un registro en Express, le diremos a Prisma de dónde importar el cliente.

Creación de nuestro modelo de base de datos

Necesitamos crear un modelo que luego ejecutará una migración. Lo que hice aquí fue un pequeño hack - Prisma necesita que escribas todos tus modelos de base de datos manualmente. Bueno, estamos consumiendo un webhook de la API de Messages API de Vonageasí que ¿qué pasa si navego a la referencia webhook en la OpenAPIcopiaba el JSON de ejemplo y hacía que AI me escribiera el modelo? Eso es exactamente lo que hice.

Screenshot of ChatGPT responding to my request to generate a model from the OpenAPI SpecAuto-generated AI code from OpenAPI specsTe ahorraré el trabajo, puedes copiar los siguientes modelos en tu schema.prisma below el datasource y el cliente:

model WebhookEvent {
 id            String   @id @default(uuid())
 channel       String
 messageUuid   String   @unique
 to            String
 from          String
 timestamp     DateTime
 contextStatus String
 messageType   String
 location      Location?
 createdAt     DateTime @default(now())
}

model Location {
 id        String  @id @default(uuid())
 webhookId String  @unique
 lat       Float
 long      Float
 webhook   WebhookEvent @relation(fields: [webhookId], references: [id], onDelete: Cascade)
}

Ahora puede ejecutar la migración, y generará tablas en la base de datos para estos modelos.

npx prisma migrate dev --name webhooks

Prisma ya ha creado la migración para usted, que sirve como registro de todos los cambios realizados en la base de datos. ¿Quieres cambiar el nombre de un campo? Sí, nueva migración, registrada en el código fuente. Ahora tiene un registro total de cómo llevar la base de datos de su aplicación al estado correcto, en código.

Creación de nuestra aplicación Express para gestionar Webhooks

Su tarea final es crear la aplicación Express que consumirá el webhook. Crea un nuevo directorio en la raíz del proyecto llamado src y crea un nuevo archivo TypeScript llamado index.ts. Su aspecto es el siguiente:

import express, { Express, Request, Response } from "express";
import dotenv from 'dotenv';
import { PrismaClient } from ".prisma/client"

dotenv.config();

const app: Express = express();
const port = process.env.PORT;
const prisma = new PrismaClient();

app.use(express.json())

app.get('/', (req: Request, res: Response) => {
 res.send('Express + TypeScript Server');
});

app.post('/webhook', async (req, res) => {
 try {
   const { channel, message_uuid, to, from, timestamp, context_status, message_type, location } = req.body
   // Save the webhook data in the database
   const webhook = await prisma.webhookEvent.create({
     data: {
       channel,
       messageUuid: message_uuid,
       to,
       from,
       timestamp: new Date(timestamp),
       contextStatus: context_status,
       messageType: message_type,
       location: location ? {
         create: {
           lat: location.lat,
           long: location.long
         }
       } : undefined
     },
     include: { location: true } // Optional: Include related location in the response
   })

   console.log('Webhook saved:', webhook)
   res.status(201).json({ message: 'Webhook saved successfully', webhook })
 } catch (error) {
   console.error('Error saving webhook:', error)
   res.status(500).json({ error: 'Internal server error' })
 }
})

app.listen(port, () => {
 console.log(`[server]: Server is running at http://localhost:${port}`);
});

Hay mucho que desentrañar aquí, así que vayamos línea por línea:

  • import { PrismaClient } from ".prisma/client" asegúrese de que importa desde el directorio .prisma.

  • app.use(express.json()) es asegurarse de que Express sabe que necesita manejar JSON.

  • app.post('/webook') define un nuevo POST al que Vonage enviará datos.

  • El const definido en el cierre del webhook extrae todos los campos que necesita a variables inmutables, que se escribirán en la base de datos

  • Por último, prisma.webhookEvent.create() que escribe los datos recibidos en la base de datos SQLite.

Necesitarás la capacidad de reconstruir tu cliente Prisma a través de la línea de comandos, además de las opciones añadidas para que TypeScript compilado funcione. En la sección scripts de su archivo package.json archivo, cámbialo por lo siguiente

"scripts": {
 "test": "echo \"Error: no test specified\" && exit 1",
 "build": "npm run prisma:generate && npx tsc",
 "start": "node dist/src/index.js",
 "dev": "nodemon --exec ts-node src/index.ts",
 "prisma:generate": "prisma generate"
}

Para ejecutar su aplicación aquí, primero compile la aplicación en el directorio dist y luego ejecute la aplicación Express, después de haber regenerado Prisma y llamado al compilador TypeScript.

npm run buildnpm run start

Te habrás dado cuenta de que también he añadido el comando npm run dev que ejecutará el compilador de TypeScript y nodemonque hará un dev build cada vez que un archivo cambie.

La última parte consiste en enviar los datos propiamente dichos. Para ello, en primer lugar, tendremos que exponer nuestra aplicación local a Internet utilizando ngrok. Para ello, abre una nueva pestaña en tu terminal y ejecuta:

ngrok http 3000

Conozca más información sobre ngrok.

Una vez que ngrok haya abierto tus puertos, ahora deberías tener una URL pública. Esto ahora se va a configurar en Vonage.

  • Para crear una aplicación, vaya a la sección Crear una aplicación en el panel de Vonage y define un nombre para tu aplicación.

  • Si tiene intención de utilizar una API que utilice Webhooks, necesitará una clave privada. Haga clic en "Generar clave pública y privada"; la descarga debería iniciarse automáticamente. Guárdela de forma segura; esta clave no puede volver a descargarse si se pierde. Seguirá la convención de nomenclatura private_<id de su aplicación>.key. Esta clave puede utilizarse ahora para autenticar llamadas a la API. Nota: La clave no funcionará hasta que se guarde la aplicación.

  • Elija las funciones que necesite (por ejemplo, Voice, Messages, RTC, etc.) y proporcione los webhooks necesarios (por ejemplo, URL de eventos, URL de respuestas o URL de mensajes entrantes). Estos se describirán en el tutorial.

  • Para guardar e implementar, haz clic en "Generar nueva aplicación" para finalizar la configuración. Tu aplicación ahora está lista para usar con las API de Vonage.

Las claves públicas y privadas y cualquier otra opción aquí no son realmente importantes ya que no estamos haciendo una integración completa, sólo generando algunos datos. Lo que es importante es que pegues tu URL generada por Ngrok en estas dos opciones de entrada, seguidas de /webhook ya que esta es la ruta que se ha creado en Express. Siga adelante y cree la aplicación, la capacidad de mensajes debe tener este aspecto:

Screenshot of the Vonage Application dashboard configuration panel showing the webhook endpointsConfiguring your Vonage Application WebhooksTodas las respuestas al número asociado a esta aplicación se reenviarán a través de. Webhook a la URL que ha puesto aquí para la URL de entrada.

Para comprar un número de teléfono virtual, vaya a su panel API y siga los pasos que se indican a continuación.

Steps on how to purchase a phone number from the dashboard, from selecting the number and confirming the selection.Purchase a phone number

  1. Vaya a su Panel API

  2. Vaya a CONSTRUIR Y GESTIONAR > Numbers > Comprar Numbers.

  3. Elija los atributos necesarios y haga clic en Buscar

  4. Pulse el botón Comprar junto al número que desee y valide su compra

  5. Para confirmar que ha adquirido el número virtual, vaya al menú de navegación de la izquierda, en CONSTRUIR Y GESTIONAR, haga clic en Numbers y, a continuación, en Sus Numbers.

Nuestra configuración está ahora completa: envía un mensaje al número que has comprado, y todo el cableado sucederá para escribir en el evento y el mensaje entrante directamente a tu nueva base de datos SQLite. Aquí he utilizado una de mis herramientas favoritas, HTTPiepara probar el envío del webhook:

Screenshot of HTTPie window showing a successful HTTP 201 request to create the recordSuccessful Persistence WinsA través del Panel de Base de Datos de PHPStorm, abrimos la tabla webhooks, y vemos que el registro ha sido persistido correctamente:

Database Query View in WebStorm

Conclusión

Esta demo muestra la potencia de SQLite: no hicimos hicimos mucho para conseguir este código para persistir los datos entrantes. Nada de Docker, nada de sistemas relacionales en la nube. Esta introducción sirve como un puntero a donde SQLite bien podría ser útil: pequeños volúmenes de archivos de registro en rotación, lotes más pequeños de datos humanos en lugar de datos generados por máquinas, y datos de sesión. Piensa en ello como una configuración rápida similar a Redis cuando la concurrencia y el tráfico no son una preocupación. Pero, como con todas las cosas, recuerda el lema de los ingenieros: It Depends®.

¿Tienes alguna pregunta o algo que compartir? Únete a la conversación en Slack de la comunidad de Vonagey mantente actualizado con el Boletín para desarrolladoressíguenos en X (antes Twitter)suscríbete a nuestro canal de YouTube para ver tutoriales en video, y sigue la página de página para desarrolladores de Vonage en LinkedInun espacio para que los desarrolladores aprendan y se conecten con la comunidad. Mantente conectado, comparte tu progreso y entérate de las últimas noticias, consejos y eventos para desarrolladores.

Compartir:

https://a.storyblok.com/f/270183/400x385/12b3020c69/james-seconde.png
James SecondePromotor senior de desarrollo PHP

Actor de formación con una disertación sobre la comedia, llegué al desarrollo de PHP a través de la escena de las reuniones. Puedes encontrarme hablando y escribiendo sobre tecnología, o tocando/comprando discos raros de mi colección de vinilos.