Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.verifow.com/llms.txt

Use this file to discover all available pages before exploring further.

This guide covers scaling strategies for both deployment models: SaaS (multi-tenant) and Dedicated VPS (single-tenant). Choose the model that fits your customer’s security requirements and budget.

Deployment Models Overview

FactorSaaS Multi-TenantDedicated VPS (Single-Tenant)
Tenants per server10–100+ banks1 bank
Infrastructure costShared across tenantsPaid by individual customer
Data isolationLogical (row-level)Physical (separate server)
Onboarding time5 minutes2–3 hours
Monthly price to customer₦50K–₦500K₦500K–₦2M+
Best forMost banks & fintechsTier-1 banks, government agencies
Compliance levelCBN compliant + ISO 27001CBN compliant + air-gapped option
Recommendation: Start with SaaS. Offer Dedicated VPS as an Enterprise tier once you have 5–10 paying customers.

SaaS Scaling Architecture

Phase 1: Single Server (0–10 Customers)

┌─────────────────────────────────────────┐
│           Single VPS ($40–$80/mo)        │
│  ┌─────────┐  ┌─────────┐  ┌─────────┐ │
│  │  Nginx  │  │Ratel App│  │ Postgres│ │
│  │ (SSL)   │  │(API+UI) │  │   16    │ │
│  └────┬────┘  └────┬────┘  └─────────┘ │
│       │            │                    │
│  ┌────┴────────────┴────┐  ┌─────────┐ │
│  │      Redis 7         │  │ Watchman│ │
│  │   (cache/queues)     │  │(sanctions)│
│  └──────────────────────┘  └─────────┘ │
└─────────────────────────────────────────┘
Specs: 4 vCPU, 8 GB RAM, 160 GB SSD
Handles: ~100 transactions/second, ~50 concurrent dashboard users
Docker Compose services on one host:
  • ratel-app (API + dashboard)
  • ratel-postgres
  • ratel-redis
  • ratel-minio
  • ratel-watchman
  • ratel-marble (optional)
  • ratel-tirreno (optional)

Phase 2: Split App & Database (10–50 Customers)

When CPU or RAM consistently exceeds 70%:
┌─────────────────────┐         ┌─────────────────────┐
│   App VPS ($40/mo)  │◄───────►│   DB VPS ($40/mo)   │
│  ┌───────────────┐  │  private│  ┌───────────────┐  │
│  │  Nginx + SSL  │  │  network│  │  Postgres 16  │  │
│  │  Ratel App    │  │  (VPC)  │  │  (primary)    │  │
│  │  Redis        │  │         │  └───────────────┘  │
│  │  Watchman     │  │         │                     │
│  └───────────────┘  │         └─────────────────────┘
└─────────────────────┘
Changes:
  • Move Postgres to its own VPS
  • Connect via private network (DigitalOcean VPC)
  • Update DATABASE_URL in .env to point to the DB VPS private IP
# On app VPS, update .env
DATABASE_URL="postgresql://ratel:PASSWORD@10.124.0.3:5432/ratel_security"

Phase 3: Load Balanced App Tier (50–200 Customers)

                      ┌─────────────────┐
                      │  Cloudflare /   │
                      │  DigitalOcean   │
                      │  Load Balancer  │
                      └────────┬────────┘

              ┌────────────────┼────────────────┐
              ▼                ▼                ▼
       ┌────────────┐  ┌────────────┐  ┌────────────┐
       │  App VPS 1 │  │  App VPS 2 │  │  App VPS 3 │
       │ (ratel-app)│  │ (ratel-app)│  │ (ratel-app)│
       │ (watchman) │  │ (watchman) │  │ (watchman) │
       └────────────┘  └────────────┘  └────────────┘
              │                │                │
              └────────────────┼────────────────┘

                    ┌─────────────────────┐
                    │   DB Cluster        │
                    │  Postgres Primary   │
                    │  + Read Replica     │
                    └─────────────────────┘
Changes:
  • Run 2–3 app servers behind a load balancer
  • Use sticky sessions (dashboard uses JWT, so stateless -any server works)
  • Add Postgres read replica for analytics/reporting queries
  • Redis stays on each app server (caches are independent) or move to Redis Cloud / Upstash

Phase 4: Managed Services (200+ Customers)

Replace self-hosted components with managed services:
ComponentSelf-HostedManaged AlternativeWhy Switch
Postgresratel-postgresDigitalOcean Managed PostgresAutomated backups, failover, scaling
Redisratel-redisUpstash RedisServerless, global replication
Object Storageratel-minioAWS S3 / DigitalOcean SpacesInfinite scale, CDN integration
QueueBullMQ on RedisAWS SQS / RabbitMQBetter observability, DLQ handling
Architecture at scale:
┌─────────────┐     ┌─────────────┐     ┌─────────────────────────────┐
│   CDN       │────►│  API Gateway │────►│  Kubernetes / DO App Platform│
│(static UI)  │     │ (rate limit) │     │  (auto-scaling app pods)     │
└─────────────┘     └─────────────┘     └─────────────────────────────┘

          ┌────────────────────────────────────────┼────────────────────────┐
          ▼                                        ▼                        ▼
┌─────────────────────┐              ┌─────────────────────┐    ┌──────────────────┐
│  Managed Postgres   │              │  Upstash Redis      │    │  DO Spaces / S3  │
│  (primary + replica)│              │  (caching + queues) │    │  (documents, XML)│
└─────────────────────┘              └─────────────────────┘    └──────────────────┘

Dedicated VPS Scaling

For enterprise customers who demand their own server, use the automated provisioning script:
./scripts/provision-bank-vps.sh \
  --bank-name "First Bank of Nigeria" \
  --slug "firstbank" \
  --domain "compliance.firstbank.ng" \
  --admin-email "admin@firstbank.ng" \
  --with-engines

What the Script Creates

┌─────────────────────────────────────────────┐
│        Dedicated VPS (per customer)         │
│                                             │
│  ┌─────────┐  ┌─────────┐  ┌─────────────┐ │
│  │  Nginx  │  │Ratel App│  │  Postgres   │ │
│  │+ Certbot│  │+Dashboard│  │    16       │ │
│  │ (SSL)   │  │+API     │  │             │ │
│  └────┬────┘  └────┬────┘  └─────────────┘ │
│       │            │                        │
│  ┌────┴────────────┴────┐  ┌─────────────┐ │
│  │      Redis 7         │  │  Watchman   │ │
│  │   (cache/queues)     │  │ (sanctions) │ │
│  └──────────────────────┘  └─────────────┘ │
│                                             │
│  Systemd: ratel-firstbank.service           │
│  Logs: /var/log/ratel-firstbank/            │
│  Firewall: UFW (22, 80, 443 only)           │
└─────────────────────────────────────────────┘

Scaling a Single Dedicated VPS

If one bank outgrows their VPS: Option A: Vertical Scaling (easiest)
# Resize the droplet via DigitalOcean UI or CLI
doctl compute droplet-action resize <droplet-id> --size s-4vcpu-8gb
Option B: Split Services (same as SaaS Phase 2)
  • Move Postgres to a separate managed database
  • Keep app + Redis + Watchman on the original VPS
  • Update DATABASE_URL to point to the managed DB
Option C: High Availability
  • 2 app servers + 1 managed DB + DigitalOcean Load Balancer
  • This is essentially the SaaS architecture, but isolated to one customer

Scaling Decision Tree

Are you just starting out?

├── YES ──► Start with SaaS on ONE VPS (Phase 1)
│           └── Cost: ~$40/month

└── NO ──► How many paying customers?

    ├── 1–10 ──► SaaS Phase 1 (single server)

    ├── 10–50 ──► SaaS Phase 2 (split app + DB)

    ├── 50–200 ──► SaaS Phase 3 (load balanced)

    ├── 200+ ──► SaaS Phase 4 (managed services)

    └── Enterprise customer demands dedicated server?
        └── Dedicated VPS (provision-bank-vps.sh)
            └── Upsell: +₦500K/month over SaaS plan

Performance Benchmarks

These are conservative estimates on DigitalOcean droplets:
DropletvCPURAMTransactions/secConcurrent UsersTenants (SaaS)
Basic24 GB~30205–10
General48 GB~1005010–50
General816 GB~25015050–150
CPU-Optimized816 GB~500300150–300
Note: Actual throughput depends on rule complexity, sanctions list size, and whether Marble/Tirreno engines are enabled.

Monitoring & Alerting

Set up monitoring before you have 10+ customers:

DigitalOcean Monitoring (built-in)

Enable in the DO console for CPU, memory, disk, and bandwidth alerts.

Uptime Monitoring

# Simple cron health check
crontab -e

# Add this line (checks API every 5 minutes, alerts via webhook if down)
*/5 * * * * curl -f http://localhost:3001/api/v1/health || curl -X POST YOUR_ALERT_WEBHOOK

Log Aggregation

For 50+ customers, ship logs to a central service:
# Install Vector or Fluentd on each app server
# Ship to Datadog, Grafana Cloud, or self-hosted Loki

Security at Scale

SaaS Security

LayerImplementation
NetworkUFW firewall, VPC private networking
DatabaseRow-level tenant isolation, encrypted at rest
APIRate limiting per tenant, JWT auth, API key rotation
DashboardRole-based access control (RBAC), session expiry
FilesMinIO/S3 with signed URLs, no public buckets
AuditImmutable audit chain with SHA-256 hashing

Dedicated VPS Security

Same as SaaS, plus:
  • Physical isolation -no shared server with other tenants
  • Custom domain + SSL -bank-branded compliance portal
  • IP whitelisting -restrict dashboard access to bank office IPs
  • Air-gapped option -no internet egress except for sanctions list updates

Cost Comparison (Monthly, USD)

SaaS Single Server (Phase 1)

ComponentCost
DigitalOcean droplet (4vCPU/8GB)$48
Backups (20% of droplet)$10
Domain + SSL (Let’s Encrypt)$0
Total~$58

Dedicated VPS (per customer)

ComponentCost
DigitalOcean droplet (4vCPU/8GB)$48
Managed Postgres (optional)$15
Backups$10
Domain + SSL$0
Total~$73
Your pricing should be 5–10× infrastructure cost to cover support, engineering, and profit.
PlanYour Monthly PriceInfra CostMargin
SaaS Starter₦50,000 (~$33)$5 (shared)High
SaaS Growth₦150,000 (~$100)$15 (shared)High
SaaS Enterprise₦500,000 (~$333)$50 (shared)High
Dedicated VPS₦1,000,000 (~$667)$73~9×

Recommendation: Start Here

  1. Month 1–3: Deploy SaaS on a single $48 DigitalOcean droplet
  2. Month 4–6: Onboard first 5–10 customers, monitor resource usage
  3. Month 6+: Split app and DB when CPU > 70% consistently
  4. Month 9+: Offer Dedicated VPS to your first enterprise customer
  5. Year 2: Move to managed services (Managed Postgres, Upstash, S3)
Do not offer Dedicated VPS until you have at least 5 SaaS customers paying consistently. The operational overhead of managing N separate servers is significant.