Structure and organize Encore.ts services.
Every Encore service needs an encore.service.ts file:
// encore.service.ts
import { Service } from "encore.dev/service";
export default new Service("my-service");
my-service/
โโโ encore.service.ts # Service definition (required)
โโโ api.ts # API endpoints
โโโ db.ts # Database (if needed)
A service can be defined at the application root:
my-app/
โโโ package.json
โโโ encore.app
โโโ encore.service.ts
โโโ api.ts
โโโ db.ts
โโโ migrations/
โโโ 001_initial.up.sql
Each service lives in its own directory:
my-app/
โโโ encore.app
โโโ package.json
โโโ user/
โ โโโ encore.service.ts
โ โโโ api.ts
โ โโโ db.ts
โโโ order/
โ โโโ encore.service.ts
โ โโโ api.ts
โ โโโ db.ts
โโโ notification/
โโโ encore.service.ts
โโโ api.ts
Group related services into systems:
my-app/
โโโ encore.app
โโโ commerce/
โ โโโ order/
โ โ โโโ encore.service.ts
โ โโโ cart/
โ โ โโโ encore.service.ts
โ โโโ payment/
โ โโโ encore.service.ts
โโโ identity/
โ โโโ user/
โ โ โโโ encore.service.ts
โ โโโ auth/
โ โโโ encore.service.ts
โโโ comms/
โโโ email/
โ โโโ encore.service.ts
โโโ push/
โโโ encore.service.ts
Import other services from ~encore/clients:
import { user } from "~encore/clients";
export const getOrderWithUser = api(
{ method: "GET", path: "/orders/:id", expose: true },
async ({ id }): Promise<OrderWithUser> => {
const order = await getOrder(id);
const orderUser = await user.get({ id: order.userId });
return { ...order, user: orderUser };
}
);
~encore/clients for cross-service calls (never direct imports)encore-architecture when the service boundaries have not been decided