Modern operational teams run on relational data. Whether managing software sprint pipelines, multi-client SEO deliverables, real estate inventory in Lahore and Karachi, call center lead intake, or e-commerce order dispatches, businesses require the flexibility of a spreadsheet paired with the integrity of a relational database.
For years, Airtable has dominated this space. However, for organizations operating in Pakistan, proprietary SaaS platforms present severe operational and financial friction:
- Per-Seat Foreign Exchange Drain: Airtable’s Team and Business tiers range from $20 to $45 per user per month. For a 30-member agency or a 60-seat BPO operation, subscription costs quickly reach $600 to $2,700 every single month in foreign currency.
- Card Limits and Withholding Taxes: State Bank of Pakistan (SBP) foreign transaction regulations, mandatory 5% to 10% advance withholding taxes on corporate credit card remittances, and stringent monthly card limits make foreign SaaS renewals a persistent administrative bottleneck.
- Artificial Data Caps: Proprietary platforms enforce arbitrary row limitations per base (e.g., 50,000 to 125,000 rows), forcing companies to purchase top-tier enterprise contracts or archive historical logs.
- Data Sovereignty and Compliance: Storing client lists, financial ledgers, and proprietary internal data in shared overseas multi-tenant clouds raises data residency and confidentiality concerns under evolving data governance frameworks.
Baserow provides an open-source, self-hosted alternative that matches Airtable’s collaborative interface while granting complete infrastructure control. Built on standard open-source technologies—PostgreSQL, Django, Nuxt.js/Vue, and Redis—Baserow runs seamlessly on a high-speed Linux VPS hosted in Pakistan or strategically routed international datacenters.
This comprehensive engineering guide walks through the complete architecture, production Docker Compose deployment, PostgreSQL performance tuning for multi-million row bases, reverse proxy configuration with WebSocket support, automated offsite backups, and webhook automation pipelines.
Baserow Internal Architecture: How the Stack Operates
Understanding Baserow’s underlying services is critical for sizing your Linux VPS resources, diagnosing performance bottlenecks, and configuring reverse proxies.
+-----------------------------------------------------------------------+
| Incoming HTTPS / WSS |
+-----------------------------------+-----------------------------------+
|
v
+-----------------------------------------------------------------------+
| Reverse Proxy (Nginx / Caddy SSL Termination) |
+-----------------------------------+-----------------------------------+
|
+-----------------------+-----------------------+
| (HTTP /api/*) | (WSS /ws/*)
v v
+-----------------------+ +-----------------------+
| Baserow Backend | | ASGI WebSocket Node |
| (Django REST API) | | (Daphne Server) |
+-----------+-----------+ +-----------+-----------+
| |
|-------- Redis Pub/Sub Event Broadcast --------|
|
+-----------------------+-----------------------+
| | |
v v v
+-----------------------+ +-------------------+ +-----------------------+
| Celery Workers | | Redis Cache | | PostgreSQL 16 Engine |
| (Async Export/Import)| | & Task Broker | | (Dynamic Table Schemas|
+-----------------------+ +-------------------+ | JSONB, Row Storage) |
+-----------------------+
1. The PostgreSQL Relational Core
Unlike simplistic NoSQL document stores, Baserow creates actual relational database tables inside PostgreSQL for each user-defined table. When a user creates a new table or adds a column in the UI, Baserow executes dynamic DDL statements (CREATE TABLE database_table_xxx, ALTER TABLE ... ADD COLUMN field_xxx). This architecture provides genuine relational foreign keys, transactional integrity (ACID), and robust query optimization.
2. Django Backend & Application Logic
The core application logic, permission layers, role-based access control (RBAC), and REST APIs run on Python and Django. Django handles data validation, formula evaluations, formula dependency graphs, and export formatting.
3. Nuxt.js / Vue.js Reactive Frontend
The client interface is built with Vue.js and Nuxt. It employs DOM virtualization to render vast data grids smoothly. Regardless of whether a table contains 100 or 500,000 rows, the browser DOM only renders the visible viewport, preventing memory bloat and scroll stutter.
4. Redis and Celery Task Workers
Heavy operations—such as importing a 250,000-row CSV file, generating spreadsheet exports, or triggering batch webhooks—are dispatched to Celery background workers via a Redis broker. This decouples CPU-heavy batch processing from the interactive HTTP request cycle, ensuring the user interface remains snappy.
5. Daphne ASGI Real-Time WebSocket Server
Baserow supports real-time multi-user collaboration similar to Google Docs or Figma. When team members edit cells simultaneously, updates are pushed through Daphne (an ASGI WebSocket server) using Redis Pub/Sub channels. The interface instantly reflects changes, row additions, and collaborator presence without requiring page refreshes.
Infrastructure Sizing: Selecting the Right VPS
Baserow’s multi-container stack requires adequate RAM and fast disk I/O, particularly because PostgreSQL and the Daphne WebSocket workers operate concurrently with Celery background queues.
| Organization Size | Active Concurrent Users | Total Database Rows | Recommended VPS Specification |
|---|---|---|---|
| Small Team / Boutique Agency | 1 to 10 users | Up to 100,000 rows | 2 vCPU, 4 GB RAM, 60 GB NVMe Storage |
| Mid-Sized Agency / Software House | 10 to 35 users | 100,000 to 1,000,000 rows | 4 vCPU, 8 GB RAM, 120 GB NVMe Storage |
| Enterprise BPO / E-commerce Hub | 35 to 100+ users | 1,000,000 to 5,000,000+ rows | 8 vCPU, 16 GB to 32 GB RAM, 250 GB Pure NVMe |
Note: Pure NVMe storage is mandatory. Traditional spinning hard drives or slow shared network storage cannot sustain the random write operations required by PostgreSQL during concurrent multi-user editing.
Step-by-Step Production Deployment on Ubuntu Linux
This deployment procedure configures a secure, modular multi-container environment on Ubuntu 24.04 / 22.04 LTS using Docker Compose.
Step 1: Base Server Hardening and Prerequisites
Update system packages, configure the timezone to Asia/Karachi, and install required system utilities:
# Update repositories and install core dependencies
sudo apt update && sudo apt upgrade -y
sudo apt install -y curl wget git ufw fail2ban jq htop rsync
# Set server timezone
sudo timedatectl set-timezone Asia/Karachi
# Configure UFW firewall
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow 22/tcp comment "SSH Management"
sudo ufw allow 80/tcp comment "HTTP Let's Encrypt"
sudo ufw allow 443/tcp comment "HTTPS Secure Traffic"
sudo ufw --force enable
Install Docker Engine and Docker Compose Plugin from the official Docker repository:
# Add Docker's official GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# Verify installation
docker compose version
Step 2: Directory Architecture and Storage Allocation
Create dedicated system users and application directories on your primary NVMe volume:
# Create application root directory
sudo mkdir -p /opt/baserow/{data,media,postgres_data,redis_data}
sudo chown -R 1000:1000 /opt/baserow/media
cd /opt/baserow
Step 3: Production Docker Compose Configuration
Create a production docker-compose.yml file. This architecture isolates the PostgreSQL database, Redis engine, and Baserow services into a private Docker network, exposing only the necessary HTTP port to the local host interface (127.0.0.1):
# /opt/baserow/docker-compose.yml
services:
baserow-db:
image: postgres:16-alpine
container_name: baserow_postgres
restart: always
environment:
POSTGRES_USER: baserow_user
POSTGRES_PASSWORD: ReplaceWithAStrongDatabasePassword987!
POSTGRES_DB: baserow_production
volumes:
- /opt/baserow/postgres_data:/var/lib/postgresql/data
networks:
- baserow_internal
healthcheck:
test: ["CMD-SHELL", "pg_isready -U baserow_user -d baserow_production"]
interval: 10s
timeout: 5s
retries: 5
baserow-redis:
image: redis:7-alpine
container_name: baserow_redis
restart: always
command: redis-server --appendonly yes --requirepass ReplaceWithAStrongRedisPassword321!
volumes:
- /opt/baserow/redis_data:/data
networks:
- baserow_internal
healthcheck:
test: ["CMD", "redis-cli", "-a", "ReplaceWithAStrongRedisPassword321!", "ping"]
interval: 10s
timeout: 5s
retries: 5
baserow-app:
image: baserow/baserow:1.32.2
container_name: baserow_core
restart: always
depends_on:
baserow-db:
condition: service_healthy
baserow-redis:
condition: service_healthy
ports:
- "127.0.0.1:8080:80"
environment:
BASEROW_PUBLIC_URL: "https://db.yourcompany.pk"
SECRET_KEY: "GenerateA64CharacterRandomKeyUsingOpenSSLRandHex32"
DATABASE_USER: "baserow_user"
DATABASE_PASSWORD: "ReplaceWithAStrongDatabasePassword987!"
DATABASE_NAME: "baserow_production"
DATABASE_HOST: "baserow-db"
DATABASE_PORT: "5432"
REDIS_HOST: "baserow-redis"
REDIS_PORT: "6379"
REDIS_PASSWORD: "ReplaceWithAStrongRedisPassword321!"
BASEROW_ROW_PAGE_SIZE_LIMIT: "200"
BASEROW_MAX_ROW_VALUES_SIZE_MB: "10"
EMAIL_SMTP: "true"
EMAIL_SMTP_HOST: "smtp.postmarkapp.com"
EMAIL_SMTP_PORT: "587"
EMAIL_SMTP_USE_TLS: "true"
EMAIL_SMTP_USER: "your-smtp-username"
EMAIL_SMTP_PASSWORD: "your-smtp-token"
FROM_EMAIL: "[email protected]"
volumes:
- /opt/baserow/data:/baserow/data
- /opt/baserow/media:/baserow/media
networks:
- baserow_internal
networks:
baserow_internal:
driver: bridge
Generate secure secrets for the environment:
# Generate high-entropy secret key
openssl rand -hex 32
Reverse Proxy Setup: SSL Termination & WebSocket Pass-Through
Baserow relies heavily on persistent WebSocket connections for real-time collaboration. If your reverse proxy is misconfigured, users will encounter repeated connection dropouts, failed cell synchronizations, or 502 Bad Gateway errors.
Nginx Production Configuration
Install Nginx and Certbot:
sudo apt install -y nginx certbot python3-certbot-nginx
Create /etc/nginx/sites-available/baserow.conf:
# Map directives for WebSocket upgrade handling
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
upstream baserow_backend {
server 127.0.0.1:8080;
keepalive 32;
}
server {
listen 80;
listen [::]:80;
server_name db.yourcompany.pk;
# Redirect all HTTP traffic to HTTPS
location / {
return 301 https://$host$request_uri;
}
}
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name db.yourcompany.pk;
# SSL Certificates (managed by Certbot)
ssl_certificate /etc/letsencrypt/live/db.yourcompany.pk/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/db.yourcompany.pk/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
# Buffer and attachment size tuning
client_max_body_size 100M;
client_body_buffer_size 128k;
# Compression settings
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
# Primary Baserow Proxy Location
location / {
proxy_pass http://baserow_backend;
proxy_http_version 1.1;
# WebSocket headers
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
# Standard forward headers
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# Timeouts to maintain persistent WebSocket streams
proxy_connect_timeout 60s;
proxy_send_timeout 3600s;
proxy_read_timeout 3600s;
}
}
Enable the configuration and obtain SSL certificates:
sudo ln -s /etc/nginx/sites-available/baserow.conf /etc/nginx/sites-enabled/
sudo nginx -t
sudo certbot --nginx -d db.yourcompany.pk
sudo systemctl reload nginx
Tuning PostgreSQL for Multi-Million Row Tables
Default PostgreSQL configurations are designed for minimal hardware (512 MB systems) and will severely bottleneck once individual Baserow tables exceed 200,000 records.
To optimize PostgreSQL for a dedicated 8 GB or 16 GB Linux VPS with NVMe storage, configure custom database parameters.
Create /opt/baserow/postgresql.conf:
# Memory Configuration (Tuned for 8GB RAM VPS)
shared_buffers = 2GB # 25% of total system RAM
effective_cache_size = 6GB # 75% of total system RAM
maintenance_work_mem = 512MB
work_mem = 32MB # Allocable per query operation
max_connections = 100
# NVMe Storage Optimization
random_page_cost = 1.1 # Fast NVMe SSD read ratio
effective_io_concurrency = 200 # Concurrent asynchronous SSD I/O
# WAL and Checkpoint Settings
wal_buffers = 16MB
min_wal_size = 1GB
max_wal_size = 4GB
checkpoint_completion_target = 0.9
# Aggressive Autovacuum for High-Write No-Code Tables
autovacuum = on
autovacuum_max_workers = 4
autovacuum_naptime = 1min
autovacuum_vacuum_threshold = 50
autovacuum_analyze_threshold = 50
autovacuum_vacuum_scale_factor = 0.05 # Trigger vacuum at 5% row churn
autovacuum_analyze_scale_factor = 0.02 # Trigger stats update at 2% churn
autovacuum_vacuum_cost_limit = 1000
Mount this file into your baserow-db container in docker-compose.yml under volumes:
volumes:
- /opt/baserow/postgres_data:/var/lib/postgresql/data
- /opt/baserow/postgresql.conf:/etc/postgresql/postgresql.conf:ro
command: postgres -c config_file=/etc/postgresql/postgresql.conf
Restart the stack to apply the new memory parameters:
cd /opt/baserow
docker compose down && docker compose up -d
Real-Time Workflow Automation: Pairing Baserow with n8n
One of the primary reasons organizations adopt Airtable is its automated trigger ecosystem. Baserow delivers equivalent functionality through its native Webhook engine, allowing seamless pairing with a self-hosted n8n instance running on the same Linux VPS network.
+------------------+ HTTP POST Payload +---------------------+
| | --------------------------------> | |
| Baserow Table | (Event: row.created/row.updated) | Self-Hosted n8n |
| | | Workflow Engine |
+------------------+ +----------+----------+
|
+--------------------------------------------+--------------------------------------------+
| | |
v v v
+-----------------------+ +-----------------------+ +-----------------------+
| WhatsApp Business API | | Local SMS Gateway | | Automated PDF Invoice |
| (Instant Lead Alert) | | (Jazz / Telenor API) | | (FBR POS / Email) |
+-----------------------+ +-----------------------+ +-----------------------+
Configuring Baserow Webhook Triggers
- Navigate to your target Baserow table and click Table Settings > Webhooks.
- Click Create Webhook and provide your n8n webhook listener URL:
https://automation.yourcompany.pk/webhook/baserow-lead-intake. - Select relevant events:
rows.created: Triggers when an agent enters a new lead or an online form registers a submission.rows.updated: Triggers when an order status changes fromPendingtoDispatched.rows.deleted: Triggers audit logging routines.
Webhook JSON Structure
Baserow transmits structured JSON payloads that your automation engines can process immediately:
{
"event_id": "c8a4192b-8a12-4d22-9214-7221e06d9e01",
"event_type": "rows.created",
"table_id": 412,
"items": [
{
"id": 1042,
"order": "1.00000000000000000000",
"field_2410": "Muhammad Ali",
"field_2411": "+923001234567",
"field_2412": "Enterprise Cloud Migration",
"field_2413": "PKR 350,000",
"field_2414": {
"id": 84,
"value": "Urgent Qualification",
"color": "red"
}
}
]
}
Because both Baserow and n8n can reside on the same private Docker network or local loopback, webhook transactions execute in sub-millisecond timeframes with zero international API rate limits.
Automated Offsite Disaster Recovery via S3 & Rclone
A self-hosted deployment requires robust backup management. An effective disaster recovery plan incorporates:
- Daily logical dumps of the PostgreSQL database (
pg_dump). - Incremental synchronization of user file attachments (
/opt/baserow/media). - Encrypted offsite transfer to S3-compatible object storage (e.g., Cloudflare R2, Wasabi, AWS S3, or Backblaze B2).
Step 1: Install and Configure Rclone
sudo apt install -y rclone
rclone config
Configure a remote called r2-remote pointing to your S3-compatible bucket.
Step 2: Automated Production Backup Script
Create /opt/baserow/scripts/backup.sh:
#!/usr/bin/env bash
set -eo pipefail
TIMESTAMP=$(date +"%Y%m%d_%H%M%S")
BACKUP_DIR="/var/backups/baserow"
RETENTION_DAYS=14
S3_BUCKET="r2-remote:company-baserow-backups"
mkdir -p "${BACKUP_DIR}"
echo "[${TIMESTAMP}] Starting Baserow Production Backup..."
# 1. Dump PostgreSQL Database via Docker Exec
docker exec baserow_postgres pg_dump -U baserow_user -d baserow_production -Fc > "${BACKUP_DIR}/baserow_db_${TIMESTAMP}.dump"
# 2. Compress the Database Dump
gzip -9 "${BACKUP_DIR}/baserow_db_${TIMESTAMP}.dump"
# 3. Upload Database Dump to Offsite Storage
rclone copy "${BACKUP_DIR}/baserow_db_${TIMESTAMP}.dump.gz" "${S3_BUCKET}/database/"
# 4. Sync File Attachments and User Media
rclone sync /opt/baserow/media "${S3_BUCKET}/media/"
# 5. Clean up local snapshots older than retention threshold
find "${BACKUP_DIR}" -type f -name "baserow_db_*.dump.gz" -mtime +${RETENTION_DAYS} -delete
echo "[$(date +"%Y%m%d_%H%M%S")] Backup and offsite sync completed successfully."
Make the script executable and add it to cron:
sudo chmod +x /opt/baserow/scripts/backup.sh
# Run nightly at 2:00 AM Pakistan Standard Time
(crontab -l 2>/dev/null; echo "0 2 * * * /opt/baserow/scripts/backup.sh >> /var/log/baserow_backup.log 2>&1") | crontab -
When to Scale: Moving from VPS to Bare-Metal Dedicated Servers
While a high-performance Linux VPS comfortably handles up to 50 active users and hundreds of thousands of records, enterprise operations eventually encounter virtualization ceilings.
Critical Bottleneck Indicators
- Hypervisor I/O Wait Spikes: If
toporhtopdisplays consistentwa%(IO wait) exceeding 15% during daytime hours, shared disk queues are throttling PostgreSQL write operations. - CPU Steal Contention: In multi-tenant cloud environments, noisy neighbors sharing physical processor cores can cause unpredictable
st%(steal time) spikes, leading to lag during real-time typing sessions. - Massive Parallel Import / Export Workloads: Running continuous CSV imports exceeding 500,000 rows alongside 20 concurrent Celery workers exhausts virtual RAM pools, triggering Linux OOM (Out of Memory) kills.
- Regulatory and Complete Physical Isolation: Financial institutions, defense contractors, and large corporate groups frequently require dedicated physical hardware that complies with strict data isolation mandates.
When your organizational database scales to multi-gigabyte active working sets and dozens of concurrent departments, migrating to unmetered, high-frequency Dedicated Servers eliminates hypervisor overhead entirely. For organizations requiring local data routing, our low-latency Dedicated Servers in Pakistan provide bare-metal NVMe arrays, multi-core Intel Xeon and AMD EPYC processors, and direct peering with Pakistan Internet Exchange (PIE) providers.
Summary and Implementation Checklist
Deploying Baserow on a Linux VPS provides Pakistani businesses with a sovereign, cost-effective data management platform. By bypassing per-seat SaaS costs, your organization retains full control over its operational databases, eliminates foreign card processing hurdles, and establishes sub-millisecond local network speeds.
Pre-Launch Verification Checklist
- Linux VPS provisioned with pure NVMe storage and Ubuntu 24.04/22.04 LTS.
- Docker and Docker Compose configured with isolated internal container networks.
- Unique 64-character secret keys and database credentials generated.
- Nginx or Caddy configured with TLS 1.3 encryption and dedicated WebSocket pass-through headers.
- PostgreSQL memory parameters tuned for available system RAM (
shared_buffers,effective_cache_size). - SMTP email credentials verified for user invites and system alerts.
- Automated offsite backup scripts configured and verified via Rclone test restores.
Deploy Baserow on Pure NVMe Linux VPS
Eliminate expensive per-seat USD SaaS subscriptions. Run your company's relational database on Nextgen's high-performance Linux Cloud VPS with pure NVMe storage, dedicated IPv4, and 24/7 technical support.
