The most surprising thing about PlanetScale’s serverless driver is that it makes a TCP-based protocol, MySQL, work efficiently over HTTP.
Let’s see it in action. Imagine you have a Vercel Function that needs to talk to PlanetScale. Normally, this would involve opening a persistent TCP connection, which is a problem for serverless environments that spin down idle functions.
// Vercel Function (Node.js)
import mysql from '@planetscale/database';
export default async function handler(req, res) {
const conn = await mysql.connect({
host: 'aws.connect.psdb.cloud',
port: 3306, // Still specified, but not used for TCP
username: 'YOUR_USERNAME',
password: 'YOUR_PASSWORD',
});
const results = await conn.execute('SELECT * FROM users WHERE id = ?', [1]);
res.status(200).json(results);
}
This looks like a standard MySQL connection string, but the @planetscale/database library intercepts it. Instead of trying to establish a direct TCP socket to aws.connect.psdb.cloud:3306, it uses a local HTTP proxy.
Here’s how it breaks down:
- The Client Library: Your application code, running in a serverless function, uses the PlanetScale driver.
- HTTP Tunneling: The driver initiates an HTTP
CONNECTrequest to a PlanetScale-managed proxy endpoint. ThisCONNECTrequest is like asking the proxy to create a tunnel. - Proxy and Translation: The proxy receives the
CONNECTrequest, authenticates it using your provided credentials, and then establishes a real TCP connection to the PlanetScale database. It then acts as a bidirectional relay. - MySQL over HTTP: When your code sends a MySQL query (e.g.,
SELECT * FROM users), the driver serializes this query into an HTTP POST request and sends it to the proxy. The proxy forwards this HTTP request over the established TCP tunnel to the PlanetScale database. - Response Handling: The PlanetScale database processes the query and sends its MySQL-protocol response back to the proxy. The proxy then wraps this response in an HTTP response and sends it back to your driver. The driver deserializes the response and presents it as standard MySQL results to your application.
This entire process is transparent to your application code, which sees a familiar mysql interface. The magic is in the driver and the PlanetScale proxy handling the HTTP encapsulation and de-encapsulation.
The problem this solves is the cold start and scaling limitations of traditional database connections in ephemeral serverless environments. Each serverless function invocation can get a "connection" without the overhead of managing long-lived TCP sockets, which are often problematic with serverless platforms’ network configurations and scaling policies. The driver effectively abstracts away the networking complexity, allowing you to treat PlanetScale as a direct database connection from your serverless functions.
The exact levers you control are primarily the connection details themselves: host, username, and password. The driver handles the rest. You don’t configure the proxy; it’s part of the PlanetScale service. The port parameter is still required by the driver’s API to match standard MySQL clients, but it’s not used for establishing a direct TCP connection when using the serverless driver.
One thing most people don’t know is how the driver manages query execution and state. When you call conn.execute(), the driver doesn’t just send a single HTTP request. It might send multiple HTTP requests over the tunnel to perform the full MySQL handshake, prepare statements, execute, and fetch results. The driver intelligently batches these operations to minimize the round trips and latency over HTTP, making it feel as close to a direct connection as possible.
The next concept to explore is how to handle transactions and connection pooling with this HTTP-based approach.