Skip to Content
Apso is in public beta. Get started
Get startedCore conceptsOverview

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.

Apso foundation mapOne product contract. A backend your team can own.
Owned output
01
Product intent

Describe the behavior

Actors, records, permissions, tenant boundaries, and the workflows they need.

02
Schema contract

Define the model

.apsorc

Entities, fields, relationships, auth strategy, indexes, and scope.

03
Consistent generation

Build the service

NestJSFastAPIGin

APIs, migrations, guards, tests, infrastructure, and OpenAPI.

04
Product code

Extend, run, and own

src/extensions/

Add product behavior, connect the client, and deploy wherever you choose.

Repeatable structureReviewable changesPortable codebase

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.

See what Apso generates →

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.

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.

Decide these before you generate

Product questionWhere 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 stepUse it when
Build your first backendYou want a guided schema-to-API walkthrough
Start from a backend modelYour product resembles SaaS, CRM, auth, support, or another common pattern
Develop an Apso serviceYou are ready to design, generate, connect, test, and deploy
Use a coding agentYou want Claude, Codex, or another agent to apply Apso’s backend rules
Last updated on