Encore.ts is a backend framework that generates infrastructure from your TypeScript code. Define an API endpoint, and Encore automatically creates cloud infrastructure — databases, pub/sub, cron jobs, and more.
Why Encore?
- Zero boilerplate — define API, get infrastructure automatically
- Type-safe — end-to-end types from API to client
- Auto-infrastructure — databases, queues, cron from code annotations
- Local dev dashboard — traces, API explorer, architecture diagram
- Free cloud — deploy to Encore Cloud or self-host
Quick Start
npm install -g encore.dev
encore app create my-app --lang=ts
cd my-app
encore run # Dev server with dashboard at http://localhost:9400
Define APIs
// backend/user/user.ts
import { api } from 'encore.dev/api';
import { SQLDatabase } from 'encore.dev/storage/sqldb';
// Database defined in code — Encore creates it!
const db = new SQLDatabase('users', {
migrations: './migrations',
});
interface User {
id: number;
name: string;
email: string;
}
interface CreateUserParams {
name: string;
email: string;
}
// POST /user — Encore infers method from function name + params
export const create = api(
{ expose: true, method: 'POST', path: '/user' },
async (params: CreateUserParams): Promise<User> => {
const row = await db.queryRow<User>`
INSERT INTO users (name, email) VALUES (${params.name}, ${params.email})
RETURNING id, name, email
`;
return row!;
}
);
// GET /user/:id
export const get = api(
{ expose: true, method: 'GET', path: '/user/:id' },
async ({ id }: { id: number }): Promise<User> => {
const row = await db.queryRow<User>`
SELECT id, name, email FROM users WHERE id = ${id}
`;
if (!row) throw new Error('User not found');
return row;
}
);
// GET /users
export const list = api(
{ expose: true, method: 'GET', path: '/users' },
async (): Promise<{ users: User[] }> => {
const rows = await db.query<User>`SELECT id, name, email FROM users`;
return { users: rows };
}
);
Pub/Sub (Defined in Code)
import { Topic, Subscription } from 'encore.dev/pubsub';
interface UserCreatedEvent {
userId: number;
email: string;
}
// Topic — Encore creates the infrastructure!
export const userCreated = new Topic<UserCreatedEvent>('user-created', {
deliveryGuarantee: 'at-least-once',
});
// Publish
await userCreated.publish({ userId: 1, email: 'alice@example.com' });
// Subscribe — auto-creates subscription
const _ = new Subscription(userCreated, 'send-welcome-email', {
handler: async (event) => {
await sendEmail(event.email, 'Welcome!');
},
});
Cron Jobs
import { CronJob } from 'encore.dev/cron';
const _ = new CronJob('daily-cleanup', {
title: 'Clean up expired sessions',
schedule: '0 2 * * *', // 2 AM daily
endpoint: cleanup,
});
export const cleanup = api(
{ expose: false },
async () => {
await db.exec`DELETE FROM sessions WHERE expires_at < NOW()`;
}
);
Key Features
| Feature | Details |
|---|---|
| Language | TypeScript (Go also supported) |
| APIs | Auto-generated from code |
| Database | SQL from code annotations |
| Pub/Sub | From code, auto-provisioned |
| Cron | Defined in code |
| Dashboard | Local dev traces, API explorer |
| Deploy | Encore Cloud or self-host |
Resources
Building backend services? Check my Apify actors or email spinov001@gmail.com.
Top comments (0)