The Go gopher was designed by the awesome Renee French
A lightweight, open-source Snowflake emulator built with Go and DuckDB, designed for local development and testing.
⭐ Like it? Give us a star!
docker run -p 8080:8080 ghcr.io/nnnkkk7/snowflake-emulator:latestdsn := "user:pass@localhost:8080/TEST_DB/PUBLIC?account=test&protocol=http"
db, _ := sql.Open("snowflake", dsn)
rows, _ := db.Query("SELECT IFF(1>0,'yes','no')") // Snowflake SQL works!- Run integration tests locally without Snowflake credentials (Go via gosnowflake, or any language via REST API)
- Cheap & fast CI smoke tests for Snowflake SQL
- Validate Snowflake-ish SQL behavior before hitting real Snowflake
Note: This is a dev/test emulator — no auth, no clustering, no external stages, no JS stored procedures. See Limitations for details.
Snowflake Emulator provides a Snowflake-compatible SQL interface backed by DuckDB for local development and testing:
- Local & CI workflows - Run Snowflake-compatible SQL with no external dependencies
- Snowflake-compatible access -
gosnowflakedriver support and REST API v2 - SQL execution - Snowflake → DuckDB translation
Platform Support
| Platform | Docker | Binary |
|---|---|---|
| Linux x86_64 (amd64) | ✅ | ✅ |
| Linux ARM64 | ✅ | - |
| macOS x86_64 | ✅ | - |
| macOS ARM64 (Apple Silicon) | ✅ | - |
| Windows (WSL2) | ✅ | - |
Note: Binary releases are only available for Linux x86_64. This is due to DuckDB requiring CGO, which makes cross-compilation complex. For all other platforms, Docker is recommended.
Docker is the recommended installation method for all platforms.
# Pull the image
docker pull ghcr.io/nnnkkk7/snowflake-emulator:latest
# Run with in-memory database
docker run -p 8080:8080 ghcr.io/nnnkkk7/snowflake-emulator:latest
# Run with persistent storage
docker run -p 8080:8080 -v snowflake-data:/data \
-e DB_PATH=/data/snowflake.db \
ghcr.io/nnnkkk7/snowflake-emulator:latestPrerequisites:
- Go 1.24+
- GCC (for DuckDB CGO)
git clone https://github.com/nnnkkk7/snowflake-emulator.git
cd snowflake-emulator
CGO_ENABLED=1 go build -o snowflake-emulator ./cmd/server# In-memory mode (default)
./snowflake-emulator
# With persistent storage
DB_PATH=/path/to/database.db ./snowflake-emulator
# Custom port
PORT=9090 ./snowflake-emulatorpackage main
import (
"database/sql"
"fmt"
"log"
_ "github.com/snowflakedb/gosnowflake"
)
func main() {
// Connect to local emulator
dsn := "user:pass@localhost:8080/TEST_DB/PUBLIC?account=test&protocol=http"
db, err := sql.Open("snowflake", dsn)
if err != nil {
log.Fatal(err)
}
defer db.Close()
// Execute Snowflake SQL (automatically translated)
rows, err := db.Query(`
SELECT
name,
IFF(score >= 90, 'A', 'B') AS grade,
NVL(email, 'no-email') AS email
FROM users
`)
if err != nil {
log.Fatal(err)
}
defer rows.Close()
for rows.Next() {
var name, grade, email string
rows.Scan(&name, &grade, &email)
fmt.Printf("%s: %s (%s)\n", name, grade, email)
}
}# Submit a SQL statement
curl -X POST http://localhost:8080/api/v2/statements \
-H "Content-Type: application/json" \
-d '{
"statement": "SELECT IFF(1 > 0, '\''yes'\'', '\''no'\'')",
"database": "TEST_DB",
"schema": "PUBLIC"
}'
# Get statement result
curl http://localhost:8080/api/v2/statements/{handle}
# Create a database
curl -X POST http://localhost:8080/api/v2/databases \
-H "Content-Type: application/json" \
-d '{"name": "MY_DB"}'
# List warehouses
curl http://localhost:8080/api/v2/warehouses| Example | Description |
|---|---|
gosnowflake/ |
Go driver example |
restapi/ |
REST API v2 example |
docker/ |
Docker container example |
# Start the emulator
go run ./cmd/server
# In another terminal, run an example
go run ./example/gosnowflake| Variable | Default | Description |
|---|---|---|
PORT |
8080 |
HTTP server port |
DB_PATH |
:memory: |
DuckDB database path (empty for in-memory) |
STAGE_DIR |
./stages |
Directory for internal stage files |
| Endpoint | Method | Description |
|---|---|---|
/session/v1/login-request |
POST | Session login |
/session/token-request |
POST | Token refresh |
/session/heartbeat |
POST | Keep-alive |
/session/renew |
POST | Renew session |
/session/logout |
POST | Logout |
/session/use |
POST | USE DATABASE/SCHEMA |
/queries/v1/query-request |
POST | Execute SQL query |
/queries/v1/abort-request |
POST | Cancel query |
| Endpoint | Method | Description |
|---|---|---|
/api/v2/statements |
POST | Submit SQL statement |
/api/v2/statements/{handle} |
GET | Get statement status/result |
/api/v2/statements/{handle}/cancel |
POST | Cancel statement |
/api/v2/databases |
GET, POST | List/Create databases |
/api/v2/databases/{db} |
GET, PUT, DELETE | Get/Alter/Drop database |
/api/v2/databases/{db}/schemas |
GET, POST | List/Create schemas |
/api/v2/databases/{db}/schemas/{schema} |
GET, DELETE | Get/Drop schema |
/api/v2/databases/{db}/schemas/{schema}/tables |
GET, POST | List/Create tables |
/api/v2/databases/{db}/schemas/{schema}/tables/{table} |
GET, PUT, DELETE | Get/Alter/Drop table |
/api/v2/warehouses |
GET, POST | List/Create warehouses |
/api/v2/warehouses/{wh} |
GET, DELETE | Get/Drop warehouse |
/api/v2/warehouses/{wh}:resume |
POST | Resume warehouse |
/api/v2/warehouses/{wh}:suspend |
POST | Suspend warehouse |
/health |
GET | Health check |
Supported SQL Operations
The emulator supports standard SQL operations with automatic Snowflake-to-DuckDB translation:
| Category | Operations | Description |
|---|---|---|
| Query | SELECT, SHOW, DESCRIBE, EXPLAIN |
Read operations with full result set support |
| DML | INSERT, UPDATE, DELETE |
Data manipulation with rows affected count |
| DDL | CREATE TABLE, DROP TABLE, ALTER TABLE |
Schema management |
| DDL | CREATE DATABASE, DROP DATABASE |
Database management |
| DDL | CREATE SCHEMA, DROP SCHEMA |
Schema namespace management |
| Transaction | BEGIN, COMMIT, ROLLBACK |
Transaction control |
| Data Loading | COPY INTO |
Bulk data loading from internal stages (CSV, JSON) |
| Upsert | MERGE INTO |
Conditional insert/update/delete operations |
Parameter Binding: Supports positional placeholder substitution (:1, :2, ?).
Supported SQL Functions
| Snowflake | DuckDB | Description |
|---|---|---|
IFF(cond, t, f) |
IF(cond, t, f) |
Conditional expression |
NVL(a, b) |
COALESCE(a, b) |
Null value substitution |
NVL2(a, b, c) |
IF(a IS NOT NULL, b, c) |
Null conditional |
IFNULL(a, b) |
COALESCE(a, b) |
Null value substitution |
DATEADD(part, n, date) |
date + INTERVAL n part |
Date arithmetic |
DATEDIFF(part, start, end) |
DATE_DIFF('part', start, end) |
Date difference |
TO_VARIANT(x) |
CAST(x AS JSON) |
Convert to variant |
PARSE_JSON(str) |
CAST(str AS JSON) |
Parse JSON string |
OBJECT_CONSTRUCT(...) |
json_object(...) |
Build JSON object |
LISTAGG(col, sep) |
STRING_AGG(col, sep) |
String aggregation |
FLATTEN(...) |
UNNEST(...) |
Array expansion |
Supported Data Types
| Snowflake Type | DuckDB Type |
|---|---|
| NUMBER, NUMERIC, DECIMAL | DOUBLE / DECIMAL(p,s) |
| INTEGER, BIGINT, SMALLINT, TINYINT | INTEGER / BIGINT |
| FLOAT, DOUBLE, REAL | DOUBLE |
| VARCHAR, STRING, TEXT, CHAR | VARCHAR |
| BOOLEAN | BOOLEAN |
| DATE | DATE |
| TIME | TIME |
| TIMESTAMP, TIMESTAMP_NTZ | TIMESTAMP |
| TIMESTAMP_LTZ, TIMESTAMP_TZ | TIMESTAMPTZ |
| VARIANT, OBJECT | JSON |
| ARRAY | JSON |
| BINARY, VARBINARY | BLOB |
| GEOGRAPHY, GEOMETRY | VARCHAR (WKT) |
This emulator is designed for development and testing. The following features are not supported:
- Authentication/Authorization (skipped in dev mode)
- Distributed processing / Clustering
- Time Travel / Zero-Copy Cloning
- Streams, Tasks, Pipes
- External stages (S3, Azure, GCS)
- Stored procedures with JavaScript
- User-defined functions
Contributions are welcome! Please feel free to submit a Pull Request.
