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

Comment maîtriser EdgeDB pour apps expertes en 2026

Read in English

Introduction

EdgeDB révolutionne les bases de données en 2026 en fusionnant le relationnel de PostgreSQL avec une sémantique graphe native, via EdgeQL, un langage déclaratif type-sûr. Pour les devs experts, c'est l'outil idéal pour modéliser des domaines complexes comme des réseaux sociaux ou e-commerce, où les jointures N-N explosent en SQL traditionnel. Imaginez querying un graphe de users → posts → comments en une ligne au lieu de 5 JOINs : gains de perf x10, schémas auto-migrés, et clients JS natifs. Ce tutoriel vous guide pas à pas sur un exemple concret d'app blog : installation, schéma avancé avec backlinks, CRUD optimisés, intégration Next.js, et pièges d'échelle. À la fin, vous déployez une instance prod-ready en <30min, prête pour 1M+ nœuds.

Prérequis

  • Docker 24+ (pour instances isolées)
  • Node.js 20+ et npm/yarn
  • Connaissances avancées en TypeScript, graphes et SQL
  • Git pour cloner un repo exemple (optionnel)
  • 4GB RAM libre pour tests locaux

Installer EdgeDB CLI et démarrer une instance

terminal-install.sh
curl --proto '=https' --tlsv1.2 -sSf https://sh edgedb.com | sh
source ~/.bashrc
edgedb instance create devblog \
  --dsn postgres://edgedb@localhost:5432/postgres \
  --password edgedb \
  --if-not-exists
edgedb instance start devblog
edgedb -I devblog instance status

Ce script télécharge l'CLI EdgeDB (version 2026 stable), crée une instance 'devblog' sur un conteneur Postgres intégré, et la démarre. Utilisez --dsn pour pointer un Postgres externe en prod ; --if-not-exists évite les doublons. Vérifiez avec status : attendez 'Ready to accept connections' pour confirmer.

Comprendre l'instance et connexion

Une instance EdgeDB encapsule un cluster Postgres avec moteur graphe. Connectez-vous via edgedb CLI ou DSN edgedb://username@localhost:10711/devblog. Pour prod, scalez avec Kubernetes : exposez port 10711, utilisez secrets pour mots de passe. Testez la connexion : edgedb -I devblog query 'SELECT 1;' doit renvoyer [{1}].

Définir le schéma de base (User et Post)

schema.esdl
module default {
  type User {
    required name: str;
    required email: str {
      constraint exclusive;
    };
    posts: array of Post;
  }

  type Post {
    required title: str;
    required content: str;
    required owner: User;
    viewers: array of User;
  }

  scalar type status_t extending str {
    constraint one_of('draft', 'published');
  };
}

Ce module .esdl définit User avec posts (array pour 1-N) et Post avec owner (required link 1:1) et viewers (N-N multi). scalar type étend str avec contraintes pour status. Sauvegardez en dbschema/default.esdl, appliquez via edgedb migration create puis edgedb migrate. Évite les pièges : toujours required pour immutables, exclusive sur emails.

Appliquer le schéma et première migration

Copiez schema.esdl dans dbschema/default.esdl. Lancez edgedb migration create --from-latest : EdgeDB génère auto une migration réversible. Appliquez avec edgedb migrate. Vérifiez : edgedb describe modules liste types. Pour itérations, EdgeDB tracke diffs et propose merges intelligents.

Insérer et query basique (CRUD User/Post)

query-crud.edgeql
INSERT User { name := 'Alice', email := 'alice@ex.com' };
INSERT Post { title := 'Mon premier post', content := 'Contenu...', owner := (SELECT User FILTER .email = 'alice@ex.com' LIMIT 1) };

SELECT User { name, posts: { title } } FILTER .name = 'Alice';

UPDATE Post FILTER .title = 'Mon premier post' SET { content += ' Ajouté!' };

DELETE Post FILTER .title LIKE '%premier%';

Ces queries EdgeQL insertent User/Post avec link via subquery FILTER (plus safe que ID). SELECT projette nested (posts.title), UPDATE append (+=), DELETE filtre LIKE. Exécutez bloc par bloc dans edgedb. Piège : LIMIT 1 sur single link évite ambiguïtés ; utilisez @@ pour computed.

Maîtriser les relations avancées (Comment + backlinks)

Ajoutez Comment avec multi-links. Backlinks auto (.owner <- post) exposent inverse. Pour N-N viewers : ALTER TYPE Post { multi link viewers := {} ; }. Query graphe : SELECT User { posts: { viewers: { name } } } unfold tout en 1 requête.

Schéma étendu avec Comment et backlinks

schema-extended.esdl
using default;

abstract type Content {
  required created_at: datetime { readonly := true };
};

type Comment extending Content {
  required text: str;
  required author: User;
  required post: Post;
};

ALTER TYPE Post {
  comments: array of Comment;
};

ALTER TYPE User {
  authored_comments: array of Comment;
};

Étends avec abstract Content pour timestamps readonly (auto-fill). Ajoute Comment linké à Post/User. Backlinks auto sur Post.comments et User.authored_comments. Migrez : edgedb migration create. Gain : queries comme SELECT Post { comments: { author: { name } } } sans JOIN.

Query experte : graphe complet avec agrégats

query-advanced.edgeql
WITH recent_posts := (SELECT Post ORDER BY .created_at DESC LIMIT 10)
SELECT User {
  name,
  post_count := count(.posts),
  avg_post_len := math::mean(.posts.content) ?? 0.0,
  recent_posts: { title, comments: { text, author: { name } } ORDER BY .created_at }
} FILTER exists .posts
ORDER BY .post_count DESC
LIMIT 5;

WITH pour CTE réutilisable, projette computed (count, math::mean), filtre exists (non-null), ordre multi-niveaux. ?? 0.0 fallback null. Exécutez après inserts : renvoie top users par posts récents avec nested comments. Perf : index auto sur created_at.

Intégrer avec client TypeScript (Next.js)

Installez @edgedb/js : npm i @edgedb/js. Créez client poolé pour scale. Dans Next.js, utilisez dans API routes ou RSC.

Client TypeScript généré et usage

lib/edgedb.ts
import { createClient } from 'edgedb';
import e from './dbschema/edgeql-js'; // généré via edgedb gen

const client = createClient();

export async function getTopUsers() {
  return e.select(e.User, (user) => ({ // type-safe!
    filter_single: { name: 'Alice' },
    name: true,
    posts: { title: true },
  }));
}

export async function createPost(userId: string, data: {title: string, content: string}) {
  return e.insert(e.Post, {
    title: data.title,
    content: data.content,
    owner: e.select(e.User, (u) => ({ filter_single: { id: userId } })),
  });
}

await client.close();

Générez types via npx edgedb-js codegen sur schema. Client poolé auto-gère connexions. Queries type-safe : IDE autocomplète filter_single. Usage async/await ; close() en shutdown. Piège : toujours await client.ensureConnected().

Bonnes pratiques

  • Toujours générer code JS : edgedb-js codegen pour typesafe queries, refactor-safe.
  • Indexez proactivement : ALTER TYPE Post CREATE INDEX ON (.created_at) pour hot paths.
  • Utilisez global edges pour computed : global current_user: User; en auth.
  • Migrez en CI/CD : edgedb migrate --dev-mode puis edgedb migrate --to-revision HEAD.
  • Monitorez avec edgedb instance logs et Prometheus exporter intégré.

Erreurs courantes à éviter

  • Oublier atomicité : EdgeDB est ACID, mais batch inserts avec FOR ... UNION pour perf, pas loops.
  • Queries non-indexées : EXPLAIN révèle scans ; ajoutez CREATE INDEX ON (User FILTER .email).
  • Cardinalité mal gérée : single link vs multi : erreur runtime si >1 ; utilisez ? pour optional.
  • Migrations manuelles : jamais RUN MIGRATION sans review ; trust auto-gen mais validez diffs.

Pour aller plus loin