DEV Community

Alex Spinov
Alex Spinov

Posted on

PlanetScale Has a Free API — Here's How to Build Scalable MySQL Apps with Branching

Why PlanetScale?

PlanetScale is serverless MySQL powered by Vitess (the same technology that scales YouTube's database). What makes it special: database branching — create branches of your schema like git branches. Test migrations without touching production.

Free tier: 5 GB storage, 1 billion row reads/month, 10M row writes/month.

Getting Started

1. Create Free Account

Sign up at planetscale.com — no credit card required.

2. Create Database & Branch

# Install PlanetScale CLI
brew install planetscale/tap/pscale

# Login
pscale auth login

# Create database
pscale database create my-app --region us-east

# Create a dev branch
pscale branch create my-app add-orders-table

# Connect to branch
pscale shell my-app add-orders-table
Enter fullscreen mode Exit fullscreen mode

3. Schema on Branch

CREATE TABLE users (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  email VARCHAR(255) UNIQUE NOT NULL,
  name VARCHAR(255) NOT NULL,
  plan ENUM('free', 'pro', 'enterprise') DEFAULT 'free',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE orders (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  user_id BIGINT NOT NULL,
  total DECIMAL(10,2) NOT NULL,
  status ENUM('pending', 'paid', 'shipped', 'delivered') DEFAULT 'pending',
  created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
  KEY idx_user (user_id),
  KEY idx_status (status)
);
Enter fullscreen mode Exit fullscreen mode

Then create a deploy request to merge to main — like a PR for your database!

Python Example

import mysql.connector

conn = mysql.connector.connect(
    host="aws.connect.psdb.cloud",
    user="your-username",
    password="your-password",
    database="my-app",
    ssl_ca="/etc/ssl/certs/ca-certificates.crt"
)
cur = conn.cursor(dictionary=True)

# Insert data
cur.executemany(
    "INSERT INTO users (email, name, plan) VALUES (%s, %s, %s)",
    [("alice@example.com", "Alice", "pro"),
     ("bob@example.com", "Bob", "free"),
     ("charlie@example.com", "Charlie", "enterprise")]
)
conn.commit()

# Analytics query
cur.execute("""
    SELECT u.plan, COUNT(*) as user_count,
           COALESCE(SUM(o.total), 0) as revenue
    FROM users u LEFT JOIN orders o ON u.id = o.user_id
    GROUP BY u.plan ORDER BY revenue DESC
""")

for row in cur.fetchall():
    print(f"{row['plan']}: {row['user_count']} users, ${row['revenue']:.2f} revenue")
Enter fullscreen mode Exit fullscreen mode

Node.js with Drizzle ORM

import { drizzle } from "drizzle-orm/planetscale-serverless";
import { connect } from "@planetscale/database";
import { mysqlTable, bigint, varchar, decimal, timestamp } from "drizzle-orm/mysql-core";

const connection = connect({ url: process.env.DATABASE_URL });
const db = drizzle(connection);

const users = mysqlTable("users", {
  id: bigint("id", { mode: "number" }).primaryKey().autoincrement(),
  email: varchar("email", { length: 255 }).unique().notNull(),
  name: varchar("name", { length: 255 }).notNull()
});

// Query
const allUsers = await db.select().from(users);
console.log(allUsers);
Enter fullscreen mode Exit fullscreen mode

Database Branching Workflow

main (production)
  └── add-orders-table (development)
       ├── Test schema changes
       ├── Run migrations safely
       └── Create deploy request → merge to main
Enter fullscreen mode Exit fullscreen mode

No more ALTER TABLE on production at 3 AM!


Need data for your PlanetScale database? I build production-ready scrapers that output structured data. Check out my Apify actors or email spinov001@gmail.com for custom data pipelines.

Using PlanetScale? Share your branching workflow below!

Top comments (0)