Skip to content

MySQL

A Railway.MySQL is MySQL as a Service: the official mysql:9 image, a Volume at /var/lib/mysql, MYSQL_* / MYSQL_URL variables, and an optional TCP proxy for the public URL. The IaC helper is Railway.mysql.

Private hostname is {name}.railway.internal. From a Service, yield ConnectMySQL. From a laptop, use publicConnectionUri.

Pass a Project. Alchemy generates a unique name, password, volume, and a public TCP proxy.

const site = yield* Railway.Project("Site");
const db = yield* Railway.MySQL("Db", { project: site });

Yield ConnectMySQL in Service init. Provide ConnectMySQLHttp. Pass conn.connectionString to Drizzle or SQL.

import * as Drizzle from "alchemy/Drizzle/MySQL";
import * as HttpServerResponse from "effect/unstable/http/HttpServerResponse";
export default class Api extends Railway.Service<Api>()(
"Api",
{
project: Site,
main: import.meta.url,
build: { install: ["mysql2"] },
},
Effect.gen(function* () {
const conn = yield* Railway.ConnectMySQL(Db);
const db = yield* Drizzle.MySQL(conn.connectionString);
return {
fetch: Effect.gen(function* () {
const rows = yield* db.execute("select 1 as ok", "objects");
return HttpServerResponse.json({ rows });
}),
};
}).pipe(Effect.provide(Railway.ConnectMySQLHttp)),
) {}

connectionString is the private URI ({name}.railway.internal:3306). Packed into the Service env — not Config.redacted.

To store Railway’s ${{Db.MYSQL_URL}} template instead of a resolved URI, pass Railway.ref (Railway.ref(Db, "MYSQL_URL")) as a Variable value.

public (default true) creates a TCP proxy on 3306. publicConnectionUri is {domain}:{proxyPort} for laptop access.

const db = yield* Railway.MySQL("Db", {
project: site,
public: false,
});

Postgres is the same shape for Postgres. Mongo is MongoDB. TcpProxy is the public TCP resource. The MySQL reference lists every prop. The ConnectMySQL reference is the runtime binding.