Platform

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

FieldTypeMutableDescription
namestringYesHuman-readable display name (e.g. Payments Service).
app_keystring (snake_case)NoMachine identifier used in database names, role names, and internal routing. Must be unique within the environment.
envenumNoOne of dev, staging, or prod. Determines default branch lifespan and network posture.

Configuration Fields

FieldTypeDefaultDescription
default_lifespanenum7d for dev, 1y for staging/prodDefault lifespan assigned to new branches.
max_branchesinteger10Hard cap on concurrent active branches.
network_modeenumrestrictedControls who can open connections. See Connections.
storage_quota_gibfloat0.25Storage allocation across all branches. Expandable to 5 GiB.
teamarray<UserRef>[creator]Users with access to this project.
tagsmap<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

  1. Payload validation — The gateway (axum on port 4060) validates the request body against the JSON Schema. app_key must be lowercase snake_case, 3–48 characters. env must be one of the three allowed values.

  2. Uniqueness check — The control plane queries its own PostgreSQL metadata database:

    SELECT id FROM projects
    WHERE app_key = $1 AND env = $2
    LIMIT 1;
  3. 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 provisioningsquare-dbctl picks up the command and executes DDL against the target Postgres cluster. See Connections for full role details.

  1. Main branch creation — A protected main branch is automatically created with lifespan forever. This branch cannot be deleted or have its lifespan changed.

  2. Token generation — PASETO v4 tokens with Ed25519 signatures are generated for the main branch. These tokens encode the project ID, branch ID, and role.

  3. Audit event — A PROJECT_CREATED event is written to the audit log.

  4. Response — The full project object plus the main branch connection credentials are returned.


What a Project Owns

A project is the parent of every resource in its scope:

ResourceRelationshipNotes
Branches1:NEach project owns 0–10 active branches. The main branch is always present.
Credentials1:N (per branch)Each branch exposes DATABASE_URL and DIRECT_URL.
Team membership1:NUsers are added at the project level; access applies to all branches.
Network policy1:1A single network_mode setting governs all branches in the project.
Audit log1:1Every mutation within the project writes to its scoped audit trail.
Storage quota1:1Quota is shared across all branches in the project.
Tags / metadata1:1Arbitrary 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 │
                    └──────────┘
StatusDescription
creatingThe project is being provisioned. Database, roles, and main branch are being set up.
activeThe project is fully operational. All branches can serve connections.
updatingA configuration change (e.g. network mode, team membership) is being applied.
deletingThe project and all its branches are being torn down.
deletedThe 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:

ModeDescription
restrictedOnly allowlisted IPs can connect. Default for all environments.
public_runtimePgBouncer URL (port 6432) is publicly accessible. Direct URL (port 5432) remains restricted.
public_allBoth 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_..." | jq

Response:

{
  "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:

  1. Set status to deleting — Prevents new branches from being created.
  2. Expire all branches — Marks every branch (except main) for immediate deletion.
  3. Delete child branchessquare-dbctl drops databases and roles for all non-main branches.
  4. Delete main branch — The protected main branch is dropped last.
  5. Drop project database — The sq_<app_key>_<env> database is dropped from the Postgres cluster.
  6. Drop all roles*_owner, *_rw, *_ro roles are dropped.
  7. Revoke tokens — All PASETO tokens for this project are invalidated.
  8. Write audit eventPROJECT_DELETED is logged.
  9. 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"
}
FieldDescription
idGlobally unique project identifier (proj_<random>).
cluster_idThe Postgres cluster this project is scheduled on. Opaque to users.
storage_used_gibCurrent total storage across all branches.
branch_countNumber of active branches.
last_activity_atTimestamp of the most recent connection or mutation.
created_byUser 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"
  }
}
EventTrigger
PROJECT_CREATEDNew project provisioned.
PROJECT_UPDATEDSettings changed (name, network mode, quota, tags).
PROJECT_TEAM_MEMBER_ADDEDUser added to project team.
PROJECT_TEAM_MEMBER_REMOVEDUser removed from project team.
PROJECT_DELETINGDeletion initiated.
PROJECT_DELETEDDeletion completed.

API Reference

MethodEndpointDescription
POST/v1/projectsCreate a new project.
GET/v1/projectsList all projects.
GET/v1/projects/:idGet a single project.
PATCH/v1/projects/:idUpdate project settings.
DELETE/v1/projects/:idDelete a project.
GET/v1/projects/:id/auditList audit events.
POST/v1/projects/:id/teamAdd a team member.
DELETE/v1/projects/:id/team/:user_idRemove a team member.

On this page