Snowflake

Lightweight, dependency-free, in-memory Snowflake SQL API v2 fake for testing code that issues SQL over the Snowflake REST SQL API. Includes a minimal real SQL engine (CREATE TABLE / INSERT / SELECT *) so round-trips actually persist and return your rows.

Default port: 4811

Quick start

import { SnowflakeServer } from "./services/snowflake/src/server.js";

const server = new SnowflakeServer(4811);
await server.start();
// ... run your app/tests ...
await server.stop();

Execute SQL via the v2 statements endpoint:

const res = await fetch("http://127.0.0.1:4811/api/v2/statements", {
  method: "POST",
  headers: { Authorization: "Bearer parlel", "Content-Type": "application/json" },
  body: JSON.stringify({ statement: "SELECT * FROM users" }),
});
const { resultSetMetaData, data } = await res.json();
// data is an array-of-arrays, e.g. [["1","Alice","true"], ...]

State is in-memory and ephemeral.

Implemented operations

Authentication is via Authorization: Bearer <token>; any non-empty bearer token is accepted.

SQL statements

SQL engine

A minimal but real engine backs the statements endpoint:

Unsupported statements / projections return a 422 with a Snowflake-style code/message/sqlState.

Service & inspection operations (parlel extensions)

Access via MCP / preview URL

In a parlel pool, the service is reachable at its preview URL (host/port shown by the pool); point your SQL API base URL at it. Through the parlel MCP server, POST /api/v2/statements is exposed as a tool surface so an AI agent can run SQL and read the array-of-arrays result without a Snowflake account.

Surface coverage

This emulator faithfully replicates the API surface most application code and agents exercise. Anything below the supported lines is either an intentional design choice for a fast, zero-cost local emulator (✓ By design) or a candidate for a future release (⟳ Roadmap) — never a silent inaccuracy.

Legend: ✅ fully supported · ◐ accepted (stored, not strictly enforced) · ✓ by design · ⟳ on the roadmap.

FeatureStatus
POST /api/v2/statements (execute)✅ Supported
GET /api/v2/statements/:handle (result by handle)✅ Supported
CREATE TABLE / INSERT / SELECT * / DROP TABLE✅ Supported (real in-memory engine)
Snowflake array-of-arrays data + resultSetMetaData.rowType✅ Supported
WHERE / JOIN / aggregates / projections other than *⟳ Roadmap — rejected with a 422 SQL compilation error, never silently wrong rows
Async statements / partitioned result retrieval◐ Single-partition synchronous results only
Bind variables (bindings)⟳ Roadmap — Not interpolated
Real warehouses / roles / databases⟳ Roadmap — Single implicit PARLEL.PUBLIC namespace
Bearer-token validity check✓ By design — Any non-empty credential is accepted — no real secrets needed

Manifest

See services/snowflake/manifest.json:

<!-- parlel:testenv:start -->

Configuration — test.env

Copy these into your test.env (used by the bridge sidecar flow). Tokens are Parlel's seeded test credentials — any non-empty value is accepted by the emulator, so you rarely need to change them. Swap in real credentials only when pointing at the live service in prod.env.

SNOWFLAKE_TOKEN=parlel
SNOWFLAKE_ACCOUNT=parlel
SNOWFLAKE_HOST=http://parlel-bridge:4811
SNOWFLAKE_BASE_URL=http://parlel-bridge:4811
<!-- parlel:testenv:end -->