Skip to content
Learni
Voir tous les tutoriels
Base de données

Comment démarrer avec Drizzle ORM en 2026

Read in English

Introduction

Drizzle ORM est un ORM léger et performant pour TypeScript, conçu pour les développeurs qui veulent écrire du SQL type-safe sans sacrifier la flexibilité. Contrairement à Prisma qui génère du JS, Drizzle compile vos schémas en requêtes SQL natives, offrant une vitesse optimale et une intégration parfaite avec PostgreSQL, MySQL ou SQLite.

Pourquoi l'utiliser en 2026 ? Les apps modernes exigent des performances élevées et une sécurité type-safe. Drizzle excelle dans les projets Next.js, Vercel ou Deno, avec un bundle zero et des migrations automatisées via Drizzle Kit. Ce tutoriel beginner vous guide pour créer une base users complète : schéma, migrations, CRUD. À la fin, vous aurez un projet fonctionnel, prêt à scaler. Imaginez comme un 'SQL avec superpouvoirs TypeScript' – simple, rapide, puissant. (128 mots)

Prérequis

  • Node.js 20+ installé
  • Connaissances de base en TypeScript
  • Un éditeur comme VS Code avec extension Drizzle
  • Pas de base de données externe : on utilise SQLite pour simplicité

Initialiser le projet

terminal
mkdir drizzle-tutorial
cd drizzle-tutorial
npm init -y
npm install drizzle-orm better-sqlite3
dnpm install -D drizzle-kit typescript @types/node tsx

On crée un nouveau projet Node.js et installe Drizzle ORM avec better-sqlite3 pour une DB locale sans setup. Les dev deps incluent drizzle-kit pour migrations et tsx pour exécuter TS directement. Cela prépare un environnement minimaliste et fonctionnel.

Configurer TypeScript

tsconfig.json
{
  "compilerOptions": {
    "target": "ES2022",
    "lib": ["ES2022"],
    "module": "ESNext",
    "moduleResolution": "bundler",
    "allowSyntheticDefaultImports": true,
    "strict": true,
    "skipLibCheck": true,
    "jsx": "react-jsx",
    "outDir": "./dist",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true
  },
  "include": ["./src/**/*"],
  "exclude": ["node_modules", "dist"]
}

Ce tsconfig.json standard active le mode strict et ES2022 pour compatibilité moderne. Il prépare le terrain pour les schémas Drizzle type-safe, évitant les erreurs de typage courantes dès le départ.

Définir le schéma de base

src/schema.ts
import { sqliteTable, text, integer } from 'drizzle-orm/sqlite-core';

export const users = sqliteTable('users', {
  id: integer('id').primaryKey({ autoIncrement: true }),
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
});

export type User = typeof users.$inferSelect;
export type NewUser = typeof users.$inferInsert;

On définit une table 'users' avec id auto-incrémenté, name et email unique. Les types User et NewUser sont inférés automatiquement pour type-safety totale. C'est la fondation : Drizzle transforme ce schéma en SQL valide.

Configurer Drizzle Kit

drizzle.config.ts
import type { Config } from 'drizzle-kit';

export default {
  schema: './src/schema.ts',
  out: './drizzle',
  dialect: 'sqlite',
  dbCredentials: {
    url: './sqlite.db',
  },
} satisfies Config;

Ce fichier configure Drizzle Kit pour générer des migrations SQL à partir du schéma. Il pointe vers SQLite local (fichier sqlite.db créé auto). Dialect 'sqlite' assure compatibilité parfaite sans serveur externe.

Générer et appliquer migrations

terminal
npx drizzle-kit generate
npx drizzle-kit migrate

La première commande génère un fichier SQL dans /drizzle basé sur schema.ts. La seconde l'exécute sur sqlite.db, créant la table users. Toujours exécuter generate avant migrate pour détecter les changements de schéma.

Connexion à la DB et requête SELECT

src/db.ts
import Database from 'better-sqlite3';
import { drizzle } from 'drizzle-orm/better-sqlite3';
import { users } from './schema';

const sqlite = new Database('./sqlite.db');
export const db = drizzle(sqlite, { schema: { users } });

On connecte Drizzle à SQLite via better-sqlite3. L'export db est réutilisable partout. Le schema option infuse les types pour des queries intellisensées.

Implémenter CRUD complet

src/index.ts
import { db } from './db';
import { users, type NewUser } from './schema';
import { eq } from 'drizzle-orm';

// INSERT
async function createUser(newUser: NewUser) {
  return await db.insert(users).values(newUser).returning();
}

// SELECT all
async function getAllUsers() {
  return await db.select().from(users);
}

// SELECT by ID
async function getUserById(id: number) {
  return await db.select().from(users).where(eq(users.id, id)).limit(1);
}

// UPDATE
async function updateUser(id: number, updates: Partial<NewUser>) {
  return await db.update(users).set(updates).where(eq(users.id, id)).returning();
}

// DELETE
async function deleteUser(id: number) {
  return await db.delete(users).where(eq(users.id, id));
}

export { createUser, getAllUsers, getUserById, updateUser, deleteUser };

Ce module implémente INSERT, SELECT, UPDATE et DELETE avec eq pour WHERE type-safe. .returning() renvoie les données modifiées. Partial permet des updates partielles sans écraser les champs.

Script d'exécution et test

src/main.ts
import { createUser, getAllUsers, getUserById, updateUser, deleteUser } from './index';

async function main() {
  // Create
  const newUser = await createUser({ name: 'Alice', email: 'alice@example.com' });
  console.log('Created:', newUser);

  // Read all
  const allUsers = await getAllUsers();
  console.log('All users:', allUsers);

  // Read one
  const user = await getUserById(1);
  console.log('User 1:', user);

  // Update
  await updateUser(1, { name: 'Alice Updated' });
  console.log('Updated user:', await getUserById(1));

  // Delete
  await deleteUser(1);
  console.log('After delete:', await getAllUsers());
}

main().catch(console.error);

Ce script teste tout le CRUD en séquence. Exécutez-le avec 'npx tsx src/main.ts' pour voir les résultats en console. Il démontre la fluidité : pas de boilerplate, queries composables.

Exécuter le projet

terminal
npx tsx src/main.ts

Cette commande lance le script de test. Vous verrez la DB se remplir, les queries s'exécuter et tout se nettoyer. Parfait pour valider que tout fonctionne sans erreur.

Bonnes pratiques

  • Toujours utiliser les types inférés : User et NewUser évitent 90% des bugs runtime.
  • Migrations en CI/CD : Intégrez 'drizzle-kit generate && migrate' dans vos pipelines.
  • Transactions pour batches : db.transaction(async tx => { tx.insert... }) pour atomicité.
  • Relations pour schémas complexes : Ajoutez pgTable.relations() dès le début.
  • Environnement vars pour prod : Remplacez './sqlite.db' par process.env.DATABASE_URL.

Erreurs courantes à éviter

  • Oublier 'npx drizzle-kit generate' avant migrate : mène à des schémas désynchronisés.
  • Utiliser raw SQL sans eq() : perd la type-safety, risque d'injections.
  • Pas de .returning() sur INSERT/UPDATE : impossible de récupérer l'ID généré.
  • Ignorer les locks SQLite en prod : passez à PostgreSQL avec neon ou vercel/postgres pour concurrency.

Pour aller plus loin

Maîtrisez les relations et indexes avec docs Drizzle. Migrez vers PostgreSQL pour prod. Découvrez nos formations Learni sur les bases de données pour Next.js + Drizzle avancé.