Why Keeping Data in a JSON File on Disk Is Better Than a Database (Until You Reach Product-Market Fit)

When launching a new web app or SaaS project, simplicity and speed are crucial. Using a JSON file instead of a database can be the smartest choice in the early stages. Here's why:

Benefits of Using JSON Files

  1. Cost-Effective
    • Running a JSON file locally costs nothing compared to managed database services like Postgres or Firebase.
    • At $0 MRR, every dollar counts, so JSON helps keep your infrastructure costs near zero.
  2. Perfect for Small Data Volumes
    • JSON works great when dealing with hundreds or thousands of records.
    • For example, if you have under 5,000 users with basic stock alerts, a JSON file will be fast enough.
  3. Simpler Codebase
    • No need to set up database connections, ORM libraries, or write SQL queries.
    • The entire data structure is a single file you can easily load, edit, and save.
  4. Fast MVP Development
    • Fewer tools, fewer dependencies, and faster shipping for a minimal viable product (MVP).

When to Switch to a Database

As your app grows, you’ll eventually outgrow JSON. Here are the signs that it’s time to transition to a database:

Key Indicators:

  • User Growth: JSON works well up to around 5,000-10,000 users. Beyond that, concurrent writes become risky.
  • Concurrent Access: JSON files are not ideal for multiple simultaneous writes. A database handles transactions safely.
  • Data Size: JSON files exceeding 50MB become slow to read/write. Databases are optimized for larger datasets.
  • Complex Queries: Searching, filtering, and aggregating data gets slower and more complicated with JSON files.
  • MRR Milestone: Once you pass $1,000 MRR, it's worth considering a database. At this point, the risk of losing customer data outweighs the simplicity benefits of JSON.

General Rule of Thumb:

  • JSON: Ideal for MVPs and up to 5,000 users or $1,000 MRR.
  • Database: Recommended for 5,000+ users, above $1,000 MRR, or complex data needs.


Example JSON Data Structures for a Stock Alerting App

Imagine you're building a stock alerting app where users can set price alerts. Here's a structured way to store the data using JSON.

Basic JSON Structure (For MVP)

{
  "users": {
    "1": {
      "email": "user1@example.com",
      "watched_tickers": ["AAPL", "TSLA"],
      "alerts": [
        {
          "ticker": "AAPL",
          "threshold": 250.00,
          "condition": "above",
          "alert_sent": false
        },
        {
          "ticker": "TSLA",
          "threshold": 380.00,
          "condition": "below",
          "alert_sent": false
        }
      ]
    }
  },
  "tickers": {
    "AAPL": {
      "current_price": 242.70
    },
    "TSLA": {
      "current_price": 394.00
    }
  }
}

Python Code to Access the Data (Basic MVP)

import json

# Load the data
def load_data():
    with open('data.json') as f:
        return json.load(f)

data = load_data()

# Access user alerts
user_id = "1"
for alert in data['users'][user_id]['alerts']:
    print(f"Alert for {alert['ticker']}: {alert['condition']} {alert['threshold']}")

Load the JSON from a file. Print all of the alerts set up for a user.

More Advanced JSON with Separate Alerts Object (Scaling a Bit More)

You may want to eventually move the alerts out of the users object into their own object for:

  • Centralized Management: Alerts are stored in a single place, making it easier to manage and update across all users.
  • Separation of Concerns: Users' data and alerts are kept distinct, resulting in a cleaner, more modular structure.
  • Scalability: Easier to scale and modify the alert system (e.g., adding fields) without complicating the user data model.
{
  "users": {
    "1": {
      "email": "user1@example.com",
      "watched_tickers": ["AAPL", "TSLA"]
    }
  },
  "tickers": {
    "AAPL": {
      "current_price": 242.70
    },
    "TSLA": {
      "current_price": 394.00
    }
  },
  "alerts": {
    "alert_1": {
      "user_id": "1",
      "ticker": "AAPL",
      "threshold": 200.00,
      "condition": "below"
      "alert_sent": false
    },
    "alert_2": {
      "user_id": "1",
      "ticker": "TSLA",
      "threshold": 350.00,
      "condition": "below",
      "alert_sent": false
    }
  }
}

Python Code to Access This Structure:

# Checking if any alerts should trigger
data = load_data()

for alert_id, alert in data['alerts'].items():
    stock = data['tickers'][alert['ticker']]
    if alert['condition'] == 'below' and stock['current_price'] < alert['threshold']:
        print(f"Sending alert to user {alert['user_id']} for {alert['ticker']}")

For each of the alerts, check if the current price has dropped below the alert threshold and send the alert.

Best Practices for Using JSON Files in Early Stages

  • File Locking: Use tools like Python's filelock to avoid data corruption with concurrent writes.
  • Data Backups: Automate periodic backups of your JSON files to prevent data loss.
  • Splitting Data: If your data grows, split files (e.g., users.json, alerts.json) instead of a single massive file.
  • Version Control: Use Git to track changes to your JSON files.
  • Read-Heavy Workloads: JSON excels when reads dominate over writes.

When to Transition to a Database (Examples)

  • <5,000 users with simple alerts: Stick with JSON files.
  • 5,000-10,000 users: If data modification frequency increases, consider SQLite.
  • 10,000+ users with real-time alerts: Postgres or a managed database is more suitable.

Why Pieter Levels Ran JSON Files for Years with Nomadlist:

Pieter Levels famously ran Nomadlist on JSON files for years because:

  • Low traffic initially.
  • Mostly read operations with minimal writes.
  • Cost efficiency before revenue generation.

Conclusion: Start Simple, Scale Smart

JSON files offer a fast, simple, and cost-effective way to manage data when you're validating a product idea. They allow you to keep your stack minimal and focus on building the product rather than managing databases.

However, once you grow past a few thousand users or need concurrent writes and real-time operations, switching to a proper database will become necessary for performance and data integrity.

✅ Build fast, validate your idea, and scale only when needed.

Read more