Labsco
encoredev logo

encore-service

โ˜… 25

by encoredev ยท part of encoredev/skills

Structures an Encore.ts app into services: how to lay out one service, several services, or groups of related services, and how they call each other over the network instead of importing code directly.

๐Ÿ”ฅ๐Ÿ”ฅ๐Ÿ”ฅโœ“ VerifiedFreeQuick setup
๐Ÿงฉ One of 28 skills in the encoredev/skills package โ€” works on its own, and pairs well with its siblings.

WHEN YOUR AGENT SHOULD USE IT

A QUICK BOUNDARY

USE FOR

  • Add a new service to an existing Encore.ts application.
  • Call an endpoint in another service instead of importing its code directly.
  • Group a large application's many services into logical systems, like commerce or identity.
  • Give a service its own dedicated database inside one Encore.ts app.

DO NOT USE FOR

  • Deciding where the boundaries between services should be in the first place.

This is the playbook your agent receives when the skill activates โ€” you don't need to read it to use the skill, but it's here to audit before installing.

Encore Service Structure

Instructions

Creating a Service

Every Encore service needs an encore.service.ts file:

// encore.service.ts
import { Service } from "encore.dev/service";

export default new Service("my-service");

Minimal Service Structure

my-service/
โ”œโ”€โ”€ encore.service.ts    # Service definition (required)
โ”œโ”€โ”€ api.ts               # API endpoints
โ””โ”€โ”€ db.ts                # Database (if needed)

Application Patterns

Single Service

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

Multi-Service

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

Large Application (System-based)

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

Service-to-Service Calls

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 };
  }
);

Guidelines

  • Services cannot be nested within other services
  • Use ~encore/clients for cross-service calls (never direct imports)
  • Each service can have its own database
  • Service names should be lowercase, descriptive
  • Don't create services just for code organization - use folders instead
  • Use encore-architecture when the service boundaries have not been decided