Intermediate4 min read

Firestore Schema

Reference documentation for the SaaSStinger Lite Firestore database structure and collections.

Firestore Schema

SaaSStinger Lite uses Cloud Firestore as its primary database.

The database is designed around a multi-workspace SaaS architecture.

The main principles are:

  • Workspace-based data isolation
  • Membership-driven authorization
  • Server-controlled writes
  • Audit visibility for administrative actions

Database Overview

The main collections are:

Firestore

├── users
│
├── workspaces
│
├── memberships
│
├── invites
│
├── projects
│
├── auditLogs
│
├── usage
│
└── notifications

Users Collection

Path:

users/{userId}

Stores user profile information.

Example:

{
  uid: string;

  email: string;

  displayName: string;

  phoneNumber: string | null;

  phoneCountryCode: string | null;

  countryOfResidence: string;

  timezone: string;

  photoURL: string | null;

  activeWorkspaceId: string | null;

  createdAt: Timestamp;

  updatedAt: Timestamp;
}

User Responsibilities

The users collection stores:

  • Profile information
  • Account preferences
  • Current workspace context

Workspace permissions are not stored here.

Permissions come from memberships.


Workspaces Collection

Path:

workspaces/{workspaceId}

Stores workspace information.

Example:

{
  name: string;

  ownerId: string;

  createdAt: Timestamp;

  updatedAt: Timestamp;
}

Workspace Responsibilities

A workspace represents a tenant inside SaaSStinger Lite.

Examples:

  • Company account
  • Team account
  • Organization account

All workspace-owned resources should reference:

workspaceId

Memberships Collection

Path:

memberships/{membershipId}

Memberships connect users to workspaces.

Example:

{
  userId: string;

  workspaceId: string;

  role:
    | "OWNER"
    | "ADMIN"
    | "MEMBER";

  createdAt: Timestamp;

  updatedAt: Timestamp;
}

Membership Rules

A user can belong to multiple workspaces.

Example:

User A

Workspace One
    ADMIN

Workspace Two
    MEMBER

Roles apply only within a workspace.


Invites Collection

Path:

invites/{token}

Stores workspace invitations.

Example:

{
  email: string;

  workspaceId: string;

  role:
    | "ADMIN"
    | "MEMBER";

  status:
    | "pending"
    | "accepted"
    | "expired";

  createdBy: string;

  createdAt: Timestamp;

  expiresAt: Timestamp;
}

Invitation Flow

Owner/Admin

      │

      ▼

Create Invite

      │

      ▼

Invite Document Created

      │

      ▼

User Accepts

      │

      ▼

Membership Created

Projects Collection

Path:

projects/{projectId}

Stores workspace projects.

Example:

{
  workspaceId: string;

  name: string;

  description?: string;

  createdBy: string;

  createdAt: Timestamp;

  updatedAt: Timestamp;
}

Project Ownership

Projects belong to workspaces.

Access should always verify:

User

        ↓

Membership

        ↓

Workspace

        ↓

Project

Audit Logs Collection

Path:

auditLogs/{auditLogId}

Stores permanent administrative activity records.

Example:

{
  workspaceId: string;

  userId: string;

  action: string;

  targetType: string;

  targetId: string;

  metadata: object;

  createdAt: Timestamp;
}

Audit Log Rules

Audit logs are:

  • Retained permanently
  • Not user deletable
  • Visible to OWNER and ADMIN roles

Usage Collection

Path:

usage/{workspaceId}

Tracks workspace usage counters.

Example:

{
  workspaceId: string;

  usersCreated: number;

  invitesCreated: number;

  auditLogsCreated: number;

  seatsUsed: number;

  updatedAt: Timestamp;
}

Usage Tracking Purpose

Usage records support:

  • Plan limits
  • Feature restrictions
  • Future billing integration

Notifications Collection

Path:

notifications/{notificationId}

Stores user notifications.

Example:

{
  userId: string;

  workspaceId: string;

  type: string;

  title: string;

  message: string;

  read: boolean;

  createdAt: Timestamp;
}

Notification Rules

Notifications are:

  • User-specific
  • Workspace-associated
  • Retained after reading

Data Relationships

Main relationships:

User

 │

 └── Membership

          │

          └── Workspace

                    │

                    ├── Projects
                    │
                    ├── Audit Logs
                    │
                    ├── Usage
                    │
                    └── Notifications

Security Model

Firestore access is controlled through:

  • Authentication
  • Membership verification
  • Role checks
  • Firestore Security Rules

The database should never rely only on client-side checks.


Adding New Collections

When adding a new collection:

  1. Define TypeScript types
  2. Add repository methods
  3. Add service logic
  4. Add server actions
  5. Update Firestore rules
  6. Add indexes if required
  7. Test with Emulator

Best Practices

  • Include workspaceId on workspace-owned data.
  • Avoid direct client database writes.
  • Keep authorization server-controlled.
  • Maintain consistent timestamps.
  • Document schema changes.

Related Articles

  • Repository Pattern
  • Adding Firestore Collections
  • Security Architecture
  • RBAC Permissions

Next Steps

Continue with Folder Structure Reference to understand the SaaSStinger Lite codebase organization.

Related Articles