Ballerina ORM
The First ORM for Ballerina
Type-safe data access with annotated records, fluent query building, and an API that feels familiar to Prisma users while staying native to Ballerina.
orm:Client db = check new ({
provider: orm:POSTGRESQL,
url: "postgresql://localhost:5432/blog"
});
User[] users = check orm:from(User)
.where({status: {equals: "ACTIVE"}})
.include({posts: true})
.take(20)
.findMany();Core Features
Designed for fast delivery and safe refactors
Type-safe queries
Generated input and filter types catch invalid query shapes before runtime.
Annotated schema
Your Ballerina record types define schema, columns, keys, indexes, and relations.
MySQL + PostgreSQL
Dialect abstraction with first-class support for both engines from day one.
Fluent API
Immutable method chaining for readable, composable and testable data access code.
Relation support
Handle 1:1, 1:N and M:N relations with include support and nested data patterns.
Raw SQL escape hatch
Use rawQuery and rawExecute when you need handcrafted SQL for edge cases.
Code Showcase
See schema and query code side by side
@orm:Entity {tableName: "users"}
public type User record {|
@orm:Id @orm:AutoIncrement
int id;
@orm:Column {nullable: false}
string email;
string name;
|};User user = check orm:from(User)
.create({
email: "jane@example.com",
name: "Jane"
});Use these patterns as building blocks, then move into full guides in the docs section.
Why Ballerina ORM?
Familiar DX with native Ballerina patterns
Fewer moving parts
Keep schema and domain types in one place using annotations directly on records.
Safer than handwritten SQL
Query shape mistakes are surfaced earlier through typed inputs and compiler feedback.
Escape hatch included
When you need tailored SQL, use raw query APIs without abandoning the ORM workflow.
| Capability | Raw SQL | bal persist | Ballerina ORM |
|---|---|---|---|
| Type-safe query input | Manual | Partial | Strong |
| Fluent filtering | Manual SQL | Limited | Built-in |
| Relations includes | Manual joins | Basic | Rich include API |
| Raw SQL escape hatch | Native | Limited | Built-in |
| Schema source of truth | SQL files | Persist models | Annotated records |
Quick Start
Go from zero to first query in minutes
Step 01
Install
Add the ORM package and configure your database connection.
bal add thambaru/bal_ormStep 02
Define Schema
Model tables using annotated Ballerina records as your source of truth.
@orm:Entity
public type User record {|
@orm:Id int id;
|};Step 03
Query
Run fluent, type-safe queries with filtering, ordering, and includes.
User[] users = check orm:from(User)
.findMany();Community
Built in the open with the Ballerina community
This section is a placeholder for usage metrics and testimonials as adoption grows. If you are building with Ballerina ORM, share your project to be featured here.
Community contributors
Growing
Open roadmap items
Active
Early adopter feedback
Welcome