Skip to Content
Apso is in public beta. Get started
Get startedCore conceptsServices and schemas

Services and schemas

An Apso service is a backend codebase with one schema contract, one generated API surface, and its own deployment and database configuration. Use one service when the entities change and deploy together. Split services when they require separate ownership, release schedules, or data boundaries.

Schema canvasProject workspace
.apsorc
Workspacetenant root
id uuidname stringslug string unique
Memberidentity
workspaceId relationuserId stringrole enum
Projectresource
workspaceId relationownerId relationstatus enum
Taskresource
projectId relationassigneeId relationdueAt datetime
Generated contract
GET/projects
POST/projects
PATCH/tasks/:id

Every tenant-owned query is scoped by workspaceId.

Model the product boundary once, then reuse it across the database, API, types, guards, and migrations.

The schema contract

The .apsorc file at the project root describes what Apso generates. Version 2 uses arrays for entities, fields, and relationships:

.apsorc
{ "version": 2, "language": "typescript", "rootFolder": "src", "entities": [ { "name": "Project", "created_at": true, "updated_at": true, "fields": [ { "name": "name", "type": "text" }, { "name": "status", "type": "enum", "values": ["Active", "Archived"], "default": "Active" } ] }, { "name": "Task", "fields": [ { "name": "title", "type": "text" }, { "name": "priority", "type": "integer", "default": 3 } ] } ], "relationships": [ { "from": "Task", "to": "Project", "type": "ManyToOne" } ] }
PropertyPurpose
versionSelects the .apsorc format. Use 2 for new projects.
languageSelects typescript, python, or go.
rootFolderSets the generated source root. The default is src.
entitiesDefines tables, fields, indexes, timestamps, scoping, and HTTP generation.
relationshipsDefines one-to-one, one-to-many, many-to-one, and many-to-many connections.
authSelects a supported session, JWT, or API-key authentication strategy.

What an entity produces

For each entity, Apso generates the ordinary framework layers needed to expose and persist it. A TypeScript service includes a TypeORM entity, DTOs, service, controller, and module registration. FastAPI and Gin projects receive the equivalent framework-native structure.

The generated CRUD routes use plural, case-preserving resource names:

GET /Projects POST /Projects GET /Projects/:id PATCH /Projects/:id DELETE /Projects/:id

Confirm the exact surface in /_docs after generation.

Edit the contract safely

  1. Change .apsorc.
  2. Run apso schema validate.
  3. Run apso generate.
  4. Inspect changes under autogen/.
  5. Run apso migrate when persisted entities changed.
  6. Add product behavior under extensions/.

Treat autogen/ as generated output. Regeneration can replace it. Keep custom endpoints, hooks, integrations, and business rules in extensions/.

Model the product, not the screen

Name entities for stable product concepts such as Workspace, Membership, Invoice, and Task. UI concepts such as Modal or DashboardCard usually do not belong in the backend schema. Start with the entities required for one complete user workflow, then add fields and relationships as those requirements become concrete.

Next steps

Last updated on