Core concepts
Apso turns a product model into a working backend foundation. The schema stays the source of truth, generation follows the same conventions every time, and product-specific behavior remains in code your team controls.
Describe the behavior
Actors, records, permissions, tenant boundaries, and the workflows they need.
Define the model
.apsorcEntities, fields, relationships, auth strategy, indexes, and scope.
Build the service
APIs, migrations, guards, tests, infrastructure, and OpenAPI.
Extend, run, and own
src/extensions/Add product behavior, connect the client, and deploy wherever you choose.
The four parts of an Apso service
1. The schema is the product contract
.apsorc describes the records your product keeps, how they relate, who can reach them, and which tenant owns them. Apso uses that contract to generate the same structure across the database, API, types, guards, and migrations.
Learn how services and schemas fit together →
2. Generation builds the repeatable foundation
Apso generates a complete NestJS, FastAPI, or Gin service. The output uses familiar framework patterns and normal package, test, and deployment tooling. You can inspect every route, entity, migration, and configuration file.
3. Extensions hold product decisions
Approvals, billing rules, integrations, and other custom workflows belong outside the generated directory. This boundary lets your team regenerate structural code without replacing the behavior that makes the product yours.
Understand the extension boundary →
4. Identity and tenant scope protect every request
Apso accepts verified identity from Better Auth or another provider. Your schema defines how records are scoped, and the generated service applies that boundary consistently to tenant-owned queries.
Plan authentication and access →
See the contract take shape
The following example models a multi-tenant project workspace. The tenant root is explicit, every resource has a clear owner, and the generated API reflects those relationships.
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.
Decide these before you generate
| Product question | Where the decision belongs |
|---|---|
| What records does the product keep? | Entities and fields in .apsorc |
| How do the records connect? | Relationships and indexes in .apsorc |
| Who can read or change each record? | Auth strategy, tenant scope, and extension logic |
| Which behavior is unique to the product? | Preserved code in src/extensions/ |
| Where will the service run? | Apso Cloud or your own deployment configuration |
Start with one complete product workflow. Model it, generate it, connect it to a client, and verify the access boundary before expanding the schema.
Continue building
| Next step | Use it when |
|---|---|
| Build your first backend | You want a guided schema-to-API walkthrough |
| Start from a backend model | Your product resembles SaaS, CRM, auth, support, or another common pattern |
| Develop an Apso service | You are ready to design, generate, connect, test, and deploy |
| Use a coding agent | You want Claude, Codex, or another agent to apply Apso’s backend rules |