The problem: non-technical team + database = chaos
Running a SaaS product. Customer support, sales, marketing teams all need access to user data. But they can't write SQL.
Before NocoDB, this was my workflow:
- Support person pings me: "Can you pull all users from X country?"
- I write a SELECT query, export CSV
- Send it to them. They ask for filters, I run more queries
- Repeat 10 times a day
Looked at Airtable - nice interface, but $20/month per user. For a team of 10, that's $2400/year. Plus data migration - moving existing database to Airtable is a pain.
Then I found NocoDB. Connect it to your existing MySQL/PostgreSQL, get a spreadsheet UI instantly. Free, open source, self-hosted.
What changed
Before: Writing SQL queries all day
After: Team uses spreadsheet UI themselves
Saved: ~15 hours/week + $2400/year vs Airtable
What NocoDB actually does
It sits on top of your existing database. Wraps your MySQL/PostgreSQL tables in a spreadsheet interface. Similar to Airtable, but connects to data you already have.
Key differences from Airtable:
- Connect your existing database - no migration needed
- Data stays in your database - full control
- Self-hosted - deploy on your own server
- Free and open source - MIT license
- Auto-generates REST API - every table gets API endpoints
- Works with MySQL, PostgreSQL, SQL Server, SQLite, MariaDB
Think of it as: phpMyAdmin meets Airtable. Or: Postico with sharing permissions.
Getting NocoDB running
Easiest way is Docker. One command:
docker run -d --name nocodb \
-p 8080:8080 \
nocodb/nocodb:latest
Access at http://localhost:8080. Create an admin account, then connect your database.
For production, use Docker Compose with your existing database:
version: "3.8"
services:
nocodb:
image: nocodb/nocodb:latest
ports:
- "8080:8080"
environment:
- NC_DB=pg://postgres:5432/u1300358_mydb
- NC_AUTH_JWT_SECRET=your-random-secret-key
depends_on:
- postgres
restart: always
postgres:
image: postgres:14
environment:
- POSTGRES_DB=mydb
- POSTGRES_USER=postgres
- POSTGRES_PASSWORD=your-password
volumes:
- postgres_data:/var/lib/postgresql/data
restart: always
volumes:
postgres_data:
Connect to cloud database (like AWS RDS):
# In NocoDB setup, select "Connect existing database"
# Enter connection details:
Host: your-db.rds.amazonaws.com
Database: production_db
User: admin
Password: your-password
If you already have a production database, just point NocoDB to it. No data migration required.
Setting up your first workspace
After connecting, NocoDB shows all your tables as spreadsheets. Let's say you have a users table:
Step 1: Configure table view
- Go to the users table in NocoDB
- Click "Add view" → Create "Active users" view
- Set filter: status = 'active'
- Hide sensitive columns (password, tokens)
- Add sort: created_at (newest first)
Step 2: Create lookup columns
If users have foreign keys to other tables, create linked columns:
// Users table has company_id
// Companies table has id, name
# In NocoDB users table:
1. Add column type "Link to another record"
2. Select "companies" table
3. Choose linking column (company_id)
4. Now user row shows company name directly
5. Click company name to jump to company record
Step 3: Add computed columns
Create formula columns for calculated data:
# Formula examples:
# User's full name:
CONCAT(first_name, ' ', last_name)
# Days since signup:
DATETIME_DIFF(NOW(), created_at, 'day')
# Account value tier:
SWITCH(
monthly_spend,
0, "Free",
10, "Basic",
50, "Pro",
"Enterprise"
)
# Customer health score:
IF(
AND(last_login > DATETIME_SUB(NOW(), 7), subscription_active),
"Healthy",
"At Risk"
)
Step 4: Set up permissions
Give team members access to specific tables:
# User roles in NocoDB:
Owner (you):
- Full access to all tables
- Can modify schema
- Can manage users
Support team:
- View: users, tickets tables
- Edit: tickets table only
- Hidden: password, payment columns
Sales team:
- View: users, companies, subscriptions tables
- Edit: companies table
- Can export data
- Cannot delete records
Marketing:
- View only access
- Cannot export
- Cannot see PII (filter out email, phone)
Now your support team can search users by email, update tickets, without ever touching SQL.
Real example: Customer support dashboard
Here's what I built for our support team. One dashboard that replaces 10 SQL queries per day.
Table 1: Active tickets by priority
Table: tickets
View: "Open by Priority"
Filters:
- status = 'open'
- assigned_to = CURRENT_USER()
Sort:
1. priority (High → Low)
2. created_at (Oldest first)
Columns shown:
- Ticket ID
- Customer (linked to users table)
- Subject
- Priority (dropdown: Low, Medium, High, Urgent)
- Status
- Created at
Actions:
- Click row → Open ticket details
- Inline edit status, priority
- Quick assign to other team members
Table 2: VIP customers needing attention
Table: users
View: "VIP Tickets"
Filters (Formula column):
- subscription_tier IN ('Pro', 'Enterprise')
- has_open_ticket = true
- ticket_age_hours > 24
Columns:
- Customer name
- Company
- Subscription tier
- Open tickets (count)
- Last ticket created
- Assigned to
Actions:
- Click customer → See all their tickets
- One-click send Slack notification
- Mark as "VIP handled"
Form for quick ticket creation
NocoDB can generate forms for data entry:
# Create "New Ticket" form view:
Fields shown:
- Customer email (with autocomplete)
- Subject (required)
- Priority (dropdown)
- Description (textarea)
- Attachments (file upload)
# Auto-set on submit:
- created_at = NOW()
- assigned_to = round-robin among team
- status = 'open'
- send notification to assigned user
Gantt view for project management
Switch to timeline view for visual planning:
Table: projects
View: "Timeline"
Configuration:
- Start date: project_start
- End date: project_deadline
- Group by: assigned_team
Shows:
- Visual timeline of all projects
- Drag to reschedule
- Color-coded by priority
- Overlap detection
Support team productivity went up 3x. They could find customer info in seconds instead of waiting for me to run queries.
Auto-generated REST API
Every table gets REST endpoints automatically. This is huge for developers.
CRUD endpoints
# For a table called "users":
# List all users
GET /api/v2/users
# Get specific user
GET /api/v2/users/123
# Create user
POST /api/v2/users
Body: { "email": "user@example.com", "name": "John" }
# Update user
PATCH /api/v2/users/123
Body: { "status": "active" }
# Delete user
DELETE /api/v2/users/123
Filtering and sorting
# Query with filters
GET /api/v2/users?where=status.active,subscription_type.pro
# Pagination
GET /api/v2/users?limit=50&offset=100
# Sorting
GET /api/v2/users?sort=-created_at
# Nested fields (joins)
GET /api/v2/users?include=company,subscription
# Full-text search
GET /api/v2/users?search=john@example.com
Authentication
# Get API token from NocoDB settings
# Then use in requests:
curl -X GET "https://nocodb.yourapp.com/api/v2/users" \
-H "xc-auth: YOUR_API_TOKEN"
Built admin panel in an hour. No need to write custom CRUD endpoints anymore.
More advanced features
Webhooks and automations
Trigger external actions on data changes:
# Webhook settings:
Trigger: When record is created in "users" table
Action: POST to https://api.slack.com/webhook
Body template:
{
"text": "New user: {{ email }}",
"blocks": [
{
"type": "section",
"text": {
"type": "mrkdwn",
"text": "New signup: *{{ email }}*\nPlan: {{ subscription_tier }}"
}
}
]
}
# Can also trigger on:
- Record updated
- Record deleted
- Specific field changes
- Scheduled (cron)
Import/export data
Bulk operations made simple:
# Import from CSV/Excel
1. Click "Import" button
2. Upload file
3. Map columns to table fields
4. Run import with validation
# Export to CSV/Excel
1. Create view with filters
2. Click "Export"
3. Choose format (CSV, Excel, JSON)
4. Get downloadable link
# Scheduled exports
- Daily backup to Google Drive
- Weekly report to Slack
- Monthly analytics export
Multiple view types
Same data, different perspectives:
Table: tasks
Views:
1. Grid (default spreadsheet)
- All columns visible
- Inline editing
2. Gallery (card view)
- Show thumbnail image
- Display status badges
- Good for visual browsing
3. Form (data entry)
- Public submission form
- Field validation
- File uploads
4. Calendar
- Date field as timeline
- Color-coded by type
- Drag to reschedule
5. Kanban
- Group by status column
- Drag to change status
- Cards show key info
6. Timeline (Gantt)
- Start/end date fields
- Project planning view
- Dependency tracking
Data validation rules
Ensure data quality at entry:
Column validation options:
- Email: Must be valid email format
- URL: Must be valid URL
- Phone: Match regex pattern
- Number: Min/max values
- Date: Date range, future only
- Select: Dropdown with allowed values
- Multi-select: Multiple from list
- Checkbox: Boolean
- Unique: No duplicates allowed
- Regex: Custom pattern matching
Problems I hit
Connection timeouts with large databases
First sync with 1M+ rows timed out. Fixed by:
# Increase timeout in docker-compose
environment:
- NC_REQUEST_TIMEOUT=300000 # 5 minutes
# Or sync specific tables only
# Use "Create table" instead of "Import from database"
# Then manually select which tables to connect
Slow queries on large tables
NocoDB adds its own queries on top of yours. Optimize:
# Add database indexes for filtered columns
CREATE INDEX idx_users_status ON users(status);
CREATE INDEX idx_tickets_assigned ON tickets(assigned_to);
# Use views instead of filtering huge tables
# Create materialized view in database, connect that to NocoDB
# Limit columns in NocoDB view
# Hide unused columns, they're not fetched
Permission edge cases
View-only user could still see sensitive data in formula columns. Fixed by:
# Use column-level permissions
# Hide sensitive columns entirely for certain roles
# Or use database views instead
CREATE VIEW users_safe AS
SELECT id, name, email, created_at
FROM users;
# Connect the view to NocoDB, not the raw table
API rate limits
High-traffic app hitting NocoDB API caused slowdowns. Fixed by:
# Don't use NocoDB API for high-traffic operations
# Use it only for admin/internal tools
# Keep your existing API for user-facing features
# Or cache API responses
# Use Redis caching for frequently accessed data
Migration between environments
Moving from dev to prod required manual config. Fixed by:
# Export NocoDB project metadata
# Settings → Project → Export metadata
# Import in new environment
# Settings → Project → Import metadata
# Or use NocoDB CLI
docker run --rm -v $(pwd)/data:/data nocodb/nocodb migrate
NocoDB vs Airtable vs others
| Feature | NocoDB | Airtable |
|---|---|---|
| Connect existing DB | Yes (MySQL, Postgres, etc) | No, requires migration |
| Self-hosted | Yes | No, cloud only |
| Pricing | Free (self-hosted) | $20-50/user/month |
| REST API | Auto-generated | Available |
| Data ownership | Your database | Airtable's servers |
| Setup difficulty | Medium (need DB) | Easy (no setup) |
| Advanced features | Growing rapidly | More mature |
| Automations | Webhooks, basic | Advanced, built-in |
If you're starting from scratch and don't have a database, Airtable is easier. If you have existing data and want control, NocoDB wins.
What I use it for now
- Support dashboard: Ticket management, customer lookup, SLA tracking
- Sales pipeline: Deal tracking, customer info, revenue forecasting
- Content management: Blog posts, SEO data, publication schedule
- User administration: Account management, subscription handling
- Analytics: Custom reports, metrics dashboard, team KPIs
- Project tracking: Task assignments, bug tracking, sprint planning
All internal tools that used to require a developer. Now the teams build and manage themselves.
Would I recommend it?
NocoDB replaced ~15 hours/week of custom internal tool development. Team can self-serve data needs without bugging engineering.
Setup takes 30 minutes if you have Docker. Learning curve is minimal if you've used spreadsheets or Airtable.
Open source and rapidly improving. New features release weekly. Community is active on Discord.
If you have a database and non-technical team members who need access, NocoDB is a no-brainer. It's Airtable for your own data.
Link: nocodb.com | GitHub: github.com/nocodb/nocodb