EdgeDB is a database that combines the relational model with a graph query language called EdgeQL. It eliminates ORMs by providing a query language that maps directly to your application objects.
Why EdgeDB Matters
SQL was designed in the 1970s for flat tables. Modern apps work with nested objects, relations, and graphs. EdgeDB bridges this gap with a query language that returns data in the shape your app needs.
What you get for free:
- EdgeQL: a modern query language that returns nested objects
- Schema-first: define types, EdgeDB creates the tables
- Built-in migrations (automatic diff-based)
- JSON output by default
- Built-in auth module
- TypeScript query builder (fully typed)
- Free cloud hosting tier
Quick Start
curl --proto '=https' --tlsv1.2 -sSf https://sh.edgedb.com | sh
edgedb project init
edgedb
Schema Definition
# dbschema/default.esdl
module default {
type User {
required name: str;
required email: str {
constraint exclusive;
};
multi posts: Post;
created_at: datetime {
default := datetime_current();
};
}
type Post {
required title: str;
required body: str;
required author: User;
multi tags: Tag;
published: bool {
default := false;
};
created_at: datetime {
default := datetime_current();
};
}
type Tag {
required name: str {
constraint exclusive;
};
}
}
edgedb migration create
edgedb migrate
EdgeQL Queries
# Insert
insert User {
name := "Alice",
email := "alice@example.com"
};
# Query with nested objects
select User {
name,
email,
posts: {
title,
body,
tags: { name },
created_at
} order by .created_at desc
} filter .email = "alice@example.com";
# Aggregation
select User {
name,
post_count := count(.posts),
latest_post := (select .posts order by .created_at desc limit 1) {
title,
created_at
}
} order by .post_count desc;
TypeScript Client
import { createClient } from "edgedb";
import e from "./dbschema/edgeql-js";
const client = createClient();
// Fully typed query builder
const users = await e.select(e.User, (user) => ({
name: true,
email: true,
posts: (post) => ({
title: true,
created_at: true,
order_by: { expression: post.created_at, direction: e.DESC },
}),
filter_single: e.op(user.email, "=", "alice@example.com"),
})).run(client);
// Insert
const newUser = await e.insert(e.User, {
name: "Bob",
email: "bob@example.com",
}).run(client);
Links
Building data-intensive apps? Check out my developer tools on Apify or email spinov001@gmail.com for custom solutions.
Top comments (0)