Projects
Workspaces that own branches, team access, network policy, backups, and audit trails in AxiomDB.
Projects
A project is the top-level organizational unit in AxiomDB. It acts as an isolated workspace that owns every resource related to a single application's database infrastructure — branches, credentials, network rules, team membership, backups, and audit history.
Think of a project as the boundary between one application (or microservice) and another. Nothing leaks across project boundaries: credentials issued in one project cannot access databases in another, network policies are evaluated per-project, and audit logs are scoped to the project that emitted them.
Project Fields
Every project is defined by three immutable identity fields plus a set of mutable configuration fields.
Identity Fields
| Field | Type | Mutable | Description |
|---|---|---|---|
name | string | Yes | Human-readable display name (e.g. Payments Service). |
app_key | string (snake_case) | No | Machine identifier used in database names, role names, and internal routing. Must be unique within the environment. |
env | enum | No | One of dev, staging, or prod. Determines default branch lifespan and network posture. |
Configuration Fields
| Field | Type | Default | Description |
|---|---|---|---|
default_lifespan | enum | 7d for dev, 1y for staging/prod | Default lifespan assigned to new branches. |
max_branches | integer | 10 | Hard cap on concurrent active branches. |
network_mode | enum | restricted | Controls who can open connections. See Connections. |
storage_quota_gib | float | 0.25 | Storage allocation across all branches. Expandable to 5 GiB. |
team | array<UserRef> | [creator] | Users with access to this project. |
tags | map<string,string> | {} | Arbitrary key-value metadata for filtering and organization. |
The (app_key, env) Uniqueness Constraint
The combination of app_key and env must be globally unique across the entire AxiomDB platform. This constraint exists because these two values directly derive database names and role names at the Postgres cluster level.
┌─────────────────────────────────────────────┐
│ Global Uniqueness │
│ │
│ (app_key="payments", env="dev") ✓ OK │
│ (app_key="payments", env="staging") ✓ OK │
│ (app_key="payments", env="dev") ✗ DUP │
└─────────────────────────────────────────────┘If you attempt to create a project with a duplicate (app_key, env) pair, the API returns 409 Conflict with error code PROJECT_ALREADY_EXISTS.
Project Creation Flow
When you call POST /v1/projects, the control plane executes the following sequence:
Client Control Plane square-dbctl Postgres Cluster
│ │ │ │
│ POST /v1/projects │ │ │
│ ─────────────────────────► │ │ │
│ │ │ │
│ │ 1. Validate payload │ │
│ │ 2. Check uniqueness │ │
│ │ (app_key, env) │ │
│ │ │ │
│ │ 3. Enqueue command │ │
│ │ CREATE_PROJECT ─────►│ │
│ │ │ │
│ │ │ 4. Create database │
│ │ │ sq_<key>_<env> ─►│
│ │ │ │
│ │ │ 5. Create roles │
│ │ │ *_owner, *_rw, │
│ │ │ *_ro ─►│
│ │ │ │
│ │ │ 6. Grant privileges │
│ │ │ owner → CREATE ─►│
│ │ │ rw → DML ─►│
│ │ │ ro → SELECT ─►│
│ │ │ │
│ │ 7. Create main branch │ │
│ │ (protected, forever) │ │
│ │ │ │
│ │ 8. Generate PASETO v4 │ │
│ │ tokens for main │ │
│ │ │ │
│ │ 9. Write audit event │ │
│ │ PROJECT_CREATED │ │
│ │ │ │
│ ◄─────────────────────── │ 10. Return project + │ │
│ 201 Created │ main branch creds │ │Step-by-Step Breakdown
-
Payload validation — The gateway (
axumon port 4060) validates the request body against the JSON Schema.app_keymust be lowercase snake_case, 3–48 characters.envmust be one of the three allowed values. -
Uniqueness check — The control plane queries its own PostgreSQL metadata database:
SELECT id FROM projects WHERE app_key = $1 AND env = $2 LIMIT 1; -
Command enqueue — The provisioning request is written to the command queue in Redis:
{ "command": "CREATE_PROJECT", "payload": { "project_id": "proj_a1b2c3d4", "app_key": "payments", "env": "prod", "creator_id": "usr_x9y8z7" }, "status": "pending", "created_at": "2025-01-15T10:30:00Z" }
4–6. Database and role provisioning — square-dbctl picks up the command and executes DDL against the target Postgres cluster. See Connections for full role details.
-
Main branch creation — A protected
mainbranch is automatically created with lifespanforever. This branch cannot be deleted or have its lifespan changed. -
Token generation — PASETO v4 tokens with Ed25519 signatures are generated for the
mainbranch. These tokens encode the project ID, branch ID, and role. -
Audit event — A
PROJECT_CREATEDevent is written to the audit log. -
Response — The full project object plus the
mainbranch connection credentials are returned.
What a Project Owns
A project is the parent of every resource in its scope:
| Resource | Relationship | Notes |
|---|---|---|
| Branches | 1:N | Each project owns 0–10 active branches. The main branch is always present. |
| Credentials | 1:N (per branch) | Each branch exposes DATABASE_URL and DIRECT_URL. |
| Team membership | 1:N | Users are added at the project level; access applies to all branches. |
| Network policy | 1:1 | A single network_mode setting governs all branches in the project. |
| Audit log | 1:1 | Every mutation within the project writes to its scoped audit trail. |
| Storage quota | 1:1 | Quota is shared across all branches in the project. |
| Tags / metadata | 1:1 | Arbitrary key-value pairs for filtering. |
What a Project Does Not Own
- Users — Users exist independently. A project references them by ID.
- Postgres clusters — Projects are scheduled onto clusters; they do not own the cluster.
- Other projects — There is no project hierarchy. Each project is a flat, isolated workspace.
- Billing — Billing is handled at the organization level, outside AxiomDB's control plane.
Project Status Values
A project transitions through the following states:
┌──────────┐
│ creating │
└────┬─────┘
│
▼
┌──────────┐
┌────►│ active │◄────┐
│ └────┬─────┘ │
│ │ │
│ ▼ │
│ ┌──────────┐ │
│ │ updating │─────┘
│ └──────────┘
│
│ ┌──────────┐
└─────│ deleting │
└────┬─────┘
│
▼
┌──────────┐
│ deleted │
└──────────┘| Status | Description |
|---|---|
creating | The project is being provisioned. Database, roles, and main branch are being set up. |
active | The project is fully operational. All branches can serve connections. |
updating | A configuration change (e.g. network mode, team membership) is being applied. |
deleting | The project and all its branches are being torn down. |
deleted | The project has been fully removed. Data is unrecoverable after the retention window. |
Project Settings
Settings can be updated via PATCH /v1/projects/:project_id:
{
"name": "Payments Service (v2)",
"network_mode": "public_runtime",
"storage_quota_gib": 2.0,
"tags": {
"team": "platform",
"cost_center": "eng-payments"
}
}Immutable fields
app_key and env cannot be changed after creation. To change either, you must create a new project and migrate data.
Network Mode
The network_mode field controls connection accessibility:
| Mode | Description |
|---|---|
restricted | Only allowlisted IPs can connect. Default for all environments. |
public_runtime | PgBouncer URL (port 6432) is publicly accessible. Direct URL (port 5432) remains restricted. |
public_all | Both URLs are publicly accessible. Use with caution. |
See Connections for full details.
Project Listing
List all projects you have access to:
curl -s https://gateway.axiomdb.io/v1/projects \
-H "Authorization: Bearer paseto_v4_..." | jqResponse:
{
"data": [
{
"id": "proj_a1b2c3d4",
"name": "Payments Service",
"app_key": "payments",
"env": "prod",
"status": "active",
"default_lifespan": "1y",
"max_branches": 10,
"network_mode": "restricted",
"storage_quota_gib": 1.0,
"storage_used_gib": 0.18,
"branch_count": 3,
"team": [
{ "user_id": "usr_x9y8z7", "role": "owner" },
{ "user_id": "usr_m3n4o5", "role": "member" }
],
"tags": { "team": "platform" },
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-03-20T14:15:00Z"
}
],
"pagination": {
"cursor": null,
"has_more": false
}
}Filtering
You can filter by env, status, and tags:
curl -s https://gateway.axiomdb.io/v1/projects?env=prod&status=active \
-H "Authorization: Bearer paseto_v4_..."Project Deletion Flow
Deleting a project is irreversible. The control plane executes:
- Set status to
deleting— Prevents new branches from being created. - Expire all branches — Marks every branch (except
main) for immediate deletion. - Delete child branches —
square-dbctldrops databases and roles for all non-main branches. - Delete main branch — The protected
mainbranch is dropped last. - Drop project database — The
sq_<app_key>_<env>database is dropped from the Postgres cluster. - Drop all roles —
*_owner,*_rw,*_roroles are dropped. - Revoke tokens — All PASETO tokens for this project are invalidated.
- Write audit event —
PROJECT_DELETEDis logged. - Set status to
deleted— The project record is soft-deleted and retained for 30 days for audit purposes.
Permanent deletion
After 30 days, the project metadata is permanently purged. There is no recovery path. Export your data before deleting.
Project Metadata
Each project carries metadata useful for tooling and automation:
{
"id": "proj_a1b2c3d4",
"cluster_id": "cls_westus2_01",
"storage_used_gib": 0.18,
"branch_count": 3,
"last_activity_at": "2025-03-20T14:15:00Z",
"created_by": "usr_x9y8z7",
"created_at": "2025-01-15T10:30:00Z",
"updated_at": "2025-03-20T14:15:00Z"
}| Field | Description |
|---|---|
id | Globally unique project identifier (proj_<random>). |
cluster_id | The Postgres cluster this project is scheduled on. Opaque to users. |
storage_used_gib | Current total storage across all branches. |
branch_count | Number of active branches. |
last_activity_at | Timestamp of the most recent connection or mutation. |
created_by | User ID of the project creator. |
Audit Events
Every project mutation emits an audit event:
{
"event": "PROJECT_CREATED",
"project_id": "proj_a1b2c3d4",
"actor_id": "usr_x9y8z7",
"actor_email": "alice@example.com",
"timestamp": "2025-01-15T10:30:00Z",
"metadata": {
"app_key": "payments",
"env": "prod",
"network_mode": "restricted"
}
}| Event | Trigger |
|---|---|
PROJECT_CREATED | New project provisioned. |
PROJECT_UPDATED | Settings changed (name, network mode, quota, tags). |
PROJECT_TEAM_MEMBER_ADDED | User added to project team. |
PROJECT_TEAM_MEMBER_REMOVED | User removed from project team. |
PROJECT_DELETING | Deletion initiated. |
PROJECT_DELETED | Deletion completed. |
API Reference
| Method | Endpoint | Description |
|---|---|---|
POST | /v1/projects | Create a new project. |
GET | /v1/projects | List all projects. |
GET | /v1/projects/:id | Get a single project. |
PATCH | /v1/projects/:id | Update project settings. |
DELETE | /v1/projects/:id | Delete a project. |
GET | /v1/projects/:id/audit | List audit events. |
POST | /v1/projects/:id/team | Add a team member. |
DELETE | /v1/projects/:id/team/:user_id | Remove a team member. |
Prisma Setup
Configure Prisma with pooled runtime traffic and a direct migration URL. Covers schema configuration, migration commands, shadow database permissions, connection pooling, and production deployment patterns.
Branches
Connectable Postgres databases with independent credentials, metrics, and configurable lifespans.