# Architecture

> Tech stack, real-time data, security, and multi-tenancy model.

This page is for technical evaluators who want to understand what the platform is built on and how it handles data, security, and scale.

---

<DocDiagram src="/docs-screens/architecture-stack.svg" alt="Seedly is a Next.js frontend on a Convex backend - run Convex Cloud by default, or self-host it; you own the full source." />

## Tech Stack

| Layer | Technology |
|-------|------------|
| Backend and Database | Convex - serverless backend with built-in database, real-time subscriptions, file storage, search indexes, and scheduled functions |
| Frontend | Next.js (App Router) with React and TypeScript |
| UI Framework | shadcn/ui + Radix Primitives + Tailwind CSS v4 |
| Authentication | Built-in (OAuth2, JWT, session management) |
| Permissions | Custom RBAC engine with frontend and backend enforcement |
| Workflow Builder | React Flow (@xyflow/react) |
| Email Templates | React Email |
| Monorepo | Turborepo + pnpm |
| Frontend Hosting | Vercel |
| Backend Hosting | Convex Cloud |
| CI/CD | GitHub Actions |
| Testing | Vitest (unit) + Playwright (E2E) |
| Error Monitoring | Sentry |
| Product Analytics | PostHog |

---

## Real-Time Architecture

Seedly CRM is real-time by default. Every data query in the application is a live subscription - when data changes on the backend, every connected client viewing that data receives the update automatically.

This is not achieved through WebSockets, polling, or manual cache invalidation. Convex provides automatic reactivity at the database layer. When a mutation writes to the database, any query that reads the affected data re-executes and pushes the new result to all subscribed clients.

In practical terms:

- When a contact replies to an SMS, the conversation updates instantly for every team member viewing it
- When someone moves an opportunity to a new pipeline stage, the kanban board updates live for all viewers
- When a workflow execution completes, the execution log reflects the result immediately
- When a team member edits a contact, the changes appear everywhere that contact is displayed

There is no "refresh" button and no stale data.

---

## Multi-Tenancy Model

The platform uses a three-tier hierarchy:

```
Agency
  |
  +-- Brand A
  |     +-- Sub-Account 1 (Client)
  |     +-- Sub-Account 2 (Client)
  |
  +-- Brand B
        +-- Sub-Account 3 (Client)
        +-- Sub-Account 4 (Client)
```

### Agency
The top-level entity. One agency owns the entire installation. The agency sets master credentials, defines plans, manages brands, and has visibility across all data.

### Brand
An organizational grouping within the agency. Brands can have their own branding, billing schedules, integration credential overrides, and design tokens. A brand admin manages the sub-accounts within their brand.

### Sub-Account
The working unit. Each sub-account represents one client and contains its own contacts, conversations, pipelines, workflows, invoices, and all other data. Sub-accounts are strictly isolated - data from one sub-account is never accessible from another.

### Data Isolation

Sub-accounts are strictly isolated at the data layer. Every backend operation resolves the authenticated user's sub-account context and enforces isolation automatically. There is no way for a query to return data from a sub-account the user does not belong to.

### Credential Cascade

Integration credentials (API keys, OAuth tokens, provider settings) resolve in order: sub-account first, then brand, then agency, then platform defaults. This means you can set credentials once at the agency level and override them selectively where needed.

---

## Security

### Authentication
- Built-in authentication with OAuth2 sign-in and signed session tokens
- Session management with token refresh and revocation
- 2FA enforcement can be enabled as a site-wide policy
- Self-hosted user accounts stored in your own backend, with no third-party identity provider required

### Authorization
- Custom role-based access control (RBAC) with four system roles and support for custom roles
- Permission matrix: 35 modules, 4 actions each (view, create, update, delete), with scope control (own, team, all)
- Backend enforcement on every mutation - all write operations are permission-checked before execution
- Frontend enforcement for UI element visibility - users only see what they can act on
- Privilege escalation prevention - users cannot create or assign roles at or above their own rank
- Feature gating by plan - modules can be enabled or disabled per subscription tier
- Usage limit enforcement - resources are metered per plan

### Data Security
- Industry-standard encryption (AES-256) for OAuth tokens and sensitive credentials stored in the database
- Runtime schema validation on every backend operation
- HTML sanitization on all user-generated content to prevent XSS

### Webhook Security
- Cryptographic signature verification on all inbound webhooks from third-party providers
- Signed payloads for outbound custom webhooks

### Audit Logging
- Every mutation is logged in the audit trail
- Audit entries include: action type, entity type, entity ID, user who performed the action, timestamp, and a diff of changes
- Filterable audit log UI: search by action, entity type, user, and date range
- Export capability for compliance

### Rate Limiting
- Per-token rate limiting on all public mutations (invoice view, estimate accept, document sign, and other customer-facing actions)
- Configurable daily send caps per sub-account for email and SMS
- Configurable refund caps (per-day count and per-refund ceiling)
- Webhook deduplication prevents double-processing on provider retries
- Workflow execution limits to prevent runaway automations

### CSP Headers
- Per-route Content Security Policy with frame-ancestors, script-src, and CAPTCHA scoping
- Hardened across all public-facing routes to prevent clickjacking and script injection

### File Upload Validation
- MIME type allowlist with magic-byte sniffing to reject disguised file types
- PNG pixel-bomb detection to prevent decompression-based denial of service
- Per-purpose size caps tailored to each upload context (profile photos, documents, attachments)

### Security Test Coverage
- A dedicated suite of **1,200+ automated security tests** covers IDOR (insecure direct object reference) and RBAC scenarios across every module
- They run in CI on every change, verifying that no user can read or write data outside their permissions or their sub-account
- Authorization is enforced on the backend for every write - the UI never decides what is allowed

---

## Scalability

Seedly CRM is built on Convex, a serverless platform that handles scaling automatically. There are no servers to provision, no database connections to pool, and no infrastructure to tune.

- **Compute** scales automatically based on load - backend functions execute on demand
- **Database** scales with usage - no connection limits, no manual sharding
- **File storage** is built into the platform with no separate object storage to manage
- **Scheduled functions** (cron jobs) run reliably without a separate job queue
- **Real-time subscriptions** scale with the number of connected clients without additional WebSocket infrastructure

The frontend is hosted on Vercel with automatic edge distribution and scaling.

---

## Hosting and Deployment

| Component | Host | Details |
|-----------|------|---------|
| Frontend | Vercel | Automatic deployments from GitHub, edge CDN, preview deployments for branches |
| Backend | Convex Cloud | Automatic deployments, zero-downtime schema migrations, built-in monitoring |
| CI/CD | GitHub Actions | Automated testing, type checking, and deployment pipelines |

Both Vercel and Convex handle SSL certificates, CDN distribution, and uptime monitoring automatically.

**Convex Cloud is the default and the fastest way to go live, but it is not a lock-in.** Because you receive the source, advanced users can run Convex locally during development and self-host it on their own servers in production. The Next.js frontend can likewise be hosted on Vercel or any platform that runs Next.js. You own and control the source for both halves of the stack.

---

## Background Processing

The platform runs scheduled background jobs for ongoing maintenance and automation, including:

- Workflow trigger evaluation and appointment reminders
- Campaign step processing and task reminders
- Conversation snooze reopening and SLA monitoring
- Review sync and review request reminders
- Notification digest batching
- Gmail and calendar watch renewal
- Email domain warmup and DNS verification
- Recurring invoice generation
- Overdue checks for tasks, invoices, and deals
- Data cleanup and engagement score maintenance

All scheduled jobs run on Convex's built-in cron system with no external job queue required.

---

## Data Retention

The platform enforces automatic data retention policies to keep storage clean and support compliance:

- **Deleted contacts (trash)** are held for a recovery window, then permanently removed along with their linked conversations and messages
- **Audit logs** are retained for a fixed compliance window
- **Webhook delivery and event-processing records** are cleaned up automatically on a rolling schedule
- **Rate-limit tracking data** is short-lived and cleared automatically

Active data (contacts, conversations, opportunities, invoices, documents) is kept indefinitely. Per-contact data erasure is available on demand for compliance with data protection requests.

---
Source: https://seedlycrm.com/docs/architecture
