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
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)
);
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")
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);
Database Branching Workflow
main (production)
└── add-orders-table (development)
├── Test schema changes
├── Run migrations safely
└── Create deploy request → merge to main
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)