Skip to main content

Data processing and storage

This page describes where data is stored, how it flows through the system, and which encryption mechanisms protect it.


Storage locations​

All data is stored within the EU/EEA. We do not use data centres outside the EU for primary data processing.

ComponentProviderRegionPurpose
Database (PostgreSQL)Supabase (AWS)eu-central-1 (Frankfurt)All application data
File storageSupabase Storage (AWS S3)eu-central-1 (Frankfurt)Uploaded files and attachments
Document storageCloudflare R2EUGenerated reports and documents
Application hostingVercelEU (via Edge Network)Web application and API
Background jobsRailwayEUAutomatic matching, report generation

Encryption​

In transit (data in transit)​

All communication between the user’s browser and Revizo is encrypted with TLS 1.2 or newer. This applies to:

  • Browser → Revizo API (HTTPS)
  • Revizo → Database (SSL/TLS)
  • Revizo → File storage (HTTPS)
  • Revizo → Third-party services (HTTPS)
  • Webhook receipt (HTTPS with signature verification)

HTTP Strict Transport Security (HSTS) is enabled with max-age=63072000 (2 years), includeSubDomains, and preload to prevent downgrade to an unencrypted connection.

At rest (data at rest)​

LayerMethodDetails
DatabaseAES-256Supabase/AWS encrypts all data at disk level
File storageAES-256Supabase Storage and Cloudflare R2 encrypt stored files
Application levelAES-256-GCMSensitive secrets (API tokens for accounting systems) are encrypted with a dedicated key before storage in the database

Application-level encryption uses AES-256-GCM (Galois/Counter Mode), which provides both confidentiality and integrity protection. The encryption key is stored as an environment variable and is rotated as needed.


Data flow​

User interaction​

User (browser)
│
│ HTTPS / TLS 1.2+
│
▼
Vercel Edge Network (EU)
│
│ Clerk authentication
│ Session validation
│
▼
Next.js API routes
│
├── Input validation (Zod)
├── RBAC check
├── Tenant isolation
│
▼
PostgreSQL (Supabase, Frankfurt)
│
│ SSL/TLS, tenant_id filter
│
▼
Response to user

Import and reconciliation​

File import (CSV/Excel/CAMT)
│
├── MIME validation
├── Size check (max 20 MB)
├── Filename sanitisation
│
▼
Supabase Storage (encrypted, tenant-scoped)
│
▼
Parser → Transactions in database
│
▼
Smart Match (automatic matching)
│
▼
Results available to user

Integrations (Tripletex / Visma NXT)​

User connects integration
│
▼
API tokens encrypted (AES-256-GCM)
│
▼
Stored encrypted in database
│
▼
On synchronisation:
Token decrypted → API call → Data stored → Token removed from memory

Data categories​

CategoryExamplesSensitivityEncryption
User identityName, email, Clerk IDPersonal dataTLS + platform encryption
Accounting dataTransactions, balances, account numbersConfidentialTLS + platform encryption
Contact dataName, email, phone, rolePersonal dataTLS + platform encryption
Integration tokensAPI keys for Tripletex/VismaHighly sensitiveAES-256-GCM (application level)
Files and attachmentsCSV, Excel, PDF, imagesConfidentialTLS + platform encryption
AI conversationsChat with AI assistantMay contain PIITLS + platform encryption
Audit logUser actions, timestampsInternalTLS + platform encryption

Backup and recovery​

Database backup​

  • Daily snapshots via Supabase (automatic)
  • Point-in-time recovery (PITR) — recovery to any point in time within the retention period
  • Backup is stored encrypted in the same EU region as the production database

Application backup​

  • Daily automatic code backup via GitHub Actions
  • Manual backup before major changes
  • All backups are tagged and can be restored

Recovery time​

In the event of an unexpected incident, the target is:

  • RPO (Recovery Point Objective): Max 1 hour of data loss (PITR)
  • RTO (Recovery Time Objective): Max 4 hours of downtime

The recovery procedure is documented in an internal DR runbook and is verified through an annual recovery exercise against a separate test environment.


Data segregation​

Each organisation in Revizo has a unique identifier (tenant_id) that ensures data is never mixed between organisations. Isolation is enforced in three layers:

  1. Authentication — Organisation ID is taken from the authenticated session, never from the client
  2. Application layer — All database queries automatically filter on tenant_id
  3. Database — Row Level Security (RLS) provides an extra safety net

See Access control for more on how access is managed.


Last updated: March 2026