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.
id uuidname stringslug string uniqueworkspaceId relationuserId stringrole enumworkspaceId relationownerId relationstatus enumprojectId relationassigneeId relationdueAt datetimeGET/projectsPOST/projectsPATCH/tasks/:idEvery tenant-owned query is scoped by workspaceId.
The schema contract
The .apsorc file at the project root describes what Apso generates. Version 2 uses arrays for entities, fields, and relationships:
{
"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" }
]
}| Property | Purpose |
|---|---|
version | Selects the .apsorc format. Use 2 for new projects. |
language | Selects typescript, python, or go. |
rootFolder | Sets the generated source root. The default is src. |
entities | Defines tables, fields, indexes, timestamps, scoping, and HTTP generation. |
relationships | Defines one-to-one, one-to-many, many-to-one, and many-to-many connections. |
auth | Selects 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/:idConfirm the exact surface in /_docs after generation.
Edit the contract safely
- Change
.apsorc. - Run
apso schema validate. - Run
apso generate. - Inspect changes under
autogen/. - Run
apso migratewhen persisted entities changed. - 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.