Sign inSign up

localstack/snowflake-next

Verified Publisher

By LocalStack GmbH

Updated about 5 hours ago

Preview of the next-generation LocalStack for Snowflake — a local Snowflake emulator.

Buildkit cache
Image
0

10K+

localstack/snowflake-next repository overview

LocalStack

Overview

localstack/snowflake-next is a preview of the next generation of LocalStack for Snowflake — a Snowflake-compatible emulator that runs on your machine or in CI, so software and data teams can develop and test data pipelines without spending Snowflake Cloud credits.

It is a ground-up reimplementation of localstack/snowflake with the same goal: existing Snowflake clients connect unmodified. The image speaks the Snowflake driver protocol, so the Python connector, JDBC, .NET, Node.js, Go, SnowSQL, the Snowflake CLI, dbt, and SQLAlchemy all point at it by changing the host only.

☑️ Feature coverage — what the emulator supports today.

Supported today:

The feature coverage catalog lists every function (with signatures), SQL command, query feature and data type as supported, partial or not supported — every one Snowflake's SQL reference documents, so the gaps are visible alongside the coverage. It is generated from the emulator itself for every :latest build, and is also available as JSON for tooling and agents.

Being a preview, coverage is still expanding and behavior may change between releases — the LocalStack for Snowflake docs describe the current generally-available emulator, localstack/snowflake, which remains the image to use for established workflows. Most of it applies here too; where the two differ, this preview is the one still moving.

Installation

The image is public — no registry login needed:

docker pull localstack/snowflake-next:latest

NOTE: the emulator requires a valid LocalStack auth token whose license carries the Snowflake preview entitlement, passed as the LOCALSTACK_AUTH_TOKEN environment variable. It checks the license at startup and exits without serving if the token is missing or not entitled. Find your token at app.localstack.cloud, see the auth token guide for details, and talk to us to get access to the preview.

Start the emulator — docker
docker run \
  --rm -it \
  -p 127.0.0.1:4566:4566 \
  -p 127.0.0.1:443:443 \
  -e LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?} \
  localstack/snowflake-next

Publish both ports. The container serves TLS and plain HTTP on each: 4566 is LocalStack's usual port, and 443 is what lets clients connect with the connector defaults and the browser reach the worksheet at https://snowflake.localhost.localstack.cloud/.

To serve different ports, set GATEWAY_LISTEN — a comma-separated list, one listener per entry — and publish them the same way:

-e GATEWAY_LISTEN=0.0.0.0:5000 -p 127.0.0.1:5000:5000

Mapping a host port onto a different container port needs nothing else: result downloads and stage transfers follow the address each client connected on.

-p 127.0.0.1:8080:4566
Start the emulator — docker-compose

Create a docker-compose.yml file with the specified content:

services:
  snowflake:
    container_name: "snowflake-next"
    image: localstack/snowflake-next
    ports:
      - "127.0.0.1:4566:4566"
      - "127.0.0.1:443:443"
    environment:
      - LOCALSTACK_AUTH_TOKEN=${LOCALSTACK_AUTH_TOKEN:?}
      - PERSISTENCE=1
    volumes:
      - "./volume:/var/lib/localstack"

Then start it with:

docker compose up

The container bundles everything it needs and initializes its data directory on first boot. State is ephemeral by default — like every other LocalStack emulator, a restart comes up clean. Set PERSISTENCE=1 and mount /var/lib/localstack — as in the compose file above, or with a named volume (-v snowflake-next-data:/var/lib/localstack) — to keep your databases across restarts. Mounting the volume without PERSISTENCE=1 does not persist anything.

Everything the emulator writes into a bind-mounted volume belongs to the user that owns the mounted directory — the container adopts that uid instead of writing as its own — so removing the directory afterwards never needs sudo.

Web interface

Once the container is up, open https://snowflake.localhost.localstack.cloud/ for the built-in web interface: browse databases, schemas, and tables, run queries in a SQL worksheet, and review query history. On a different port, use the URL the startup log prints. GET /_localstack/health reports the running version.

Quickstart

After starting the emulator, use the Snowflake Python connector to run a query against it:

import snowflake.connector

connection = snowflake.connector.connect(
    user="test",
    password="test",
    account="test",
    # Resolves to 127.0.0.1 and matches the emulator's default TLS certificate
    host="snowflake.localhost.localstack.cloud",
)
cursor = connection.cursor()
cursor.execute("CREATE DATABASE IF NOT EXISTS test")
cursor.execute("USE DATABASE test")
cursor.execute("CREATE TABLE table1(col1 INT)")
cursor.execute("INSERT INTO table1 VALUES (42)")
print(cursor.execute("SELECT col1 FROM table1").fetchall())    # [(42,)]
.NET 10 (Snowflake.Data 4.x)

Use HTTPS, the default and recommended scheme. For an image published on host port 4566, this is Island's known-working connection string:

var connectionString = "account=test;user=test;password=test;host=snowflake.localhost.localstack.cloud;port=4566;scheme=https;insecuremode=true;role=PUBLIC;MaxPoolSize=4;MULTI_STATEMENT_COUNT=0";

role=PUBLIC is included for clarity and compatibility, but is optional. Snowflake.Data may send an omitted role as a blank roleName=; both blank and omitted values are accepted and resolve to PUBLIC in the emulator, matching the omitted-role behavior recorded against real Snowflake by test_blank_role_is_treated_as_unspecified. An explicitly named role must exist: an unknown role is rejected with error 390189, whose message suggests PUBLIC as an alternative.

The default certificate is publicly trusted, so insecuremode=true is needed only when the emulator falls back to an untrusted/self-signed certificate (or when a deployment supplies one). It is retained above because this known-working configuration also covers that fallback. MaxPoolSize=4 and MULTI_STATEMENT_COUNT=0 are client choices, not emulator requirements.

A fresh instance starts with only the SNOWFLAKE database, and a new session has no current database — create one and USE it (or pass database=... to connect() once it exists), as above.

Credentials are not verified, so any values work — but the password must be a non-empty string, since snowflake-connector-python 4.x rejects an empty one client-side before any request is sent.

snowflake.localhost.localstack.cloud resolves to 127.0.0.1 through public DNS and matches the emulator's default certificate, so TLS validates with no extra client flags. It defaults to port 443, served by the -p 443:443 mapping above. If you only publish 4566 — or your Docker installation does not allow mapping privileged host ports — add port=4566, protocol="https" to connect() instead, and open the web interface at https://snowflake.localhost.localstack.cloud:4566/.

The emulator enables HTTPS by default. On first boot it fetches the LocalStack dev certificate and caches it at /var/lib/localstack/cache/server.test.pem (reused for 24 h, and across restarts when the volume is mounted). On an air-gapped or locked-down host where the download is unreachable, it falls back to a self-signed certificate instead of dropping to plain HTTP — that certificate is not publicly trusted, so connect with insecure_mode=True. Plain-HTTP clients need none of this: every bound port serves both schemes, so protocol="http" / scheme=http works as-is. USE_SSL=false turns TLS off entirely, and that plaintext-only listener cannot serve stage PUT/GET.

An ordinary Docker host-port remap needs no LOCALSTACK_HOST: result-chunk and stage URLs inherit the port from the request's Host. LOCALSTACK_HOST only extends the browser UI's CORS allow-list. If a reverse proxy rewrites Host, set SNOWFLAKE_API_ENDPOINT to the client-visible API base URL and, when stage transfers use a separately advertised address, set SF_S3_ENDPOINT_EXTERNAL to its client-visible host:port.

Check out the documentation for more examples and guides.

Configuration

VariableDescription
LOCALSTACK_AUTH_TOKENLocalStack auth token (required)
PERSISTENCESet to 1 to keep state across restarts in the mounted /var/lib/localstack volume; ephemeral otherwise
GATEWAY_LISTENAddress(es) the server binds, comma-separated — one listener per entry (image default 0.0.0.0:4566,0.0.0.0:443)
LOCALSTACK_HOSTRead only for the browser UI's CORS allow-list, as in localstack/snowflake. Not needed for port mappings: every URL the emulator hands back follows the address the client connected on
SNOWFLAKE_INIT_SCRIPTS_DIRDirectory scanned for *.sf.sql init scripts run at startup (default /etc/localstack/init/ready.d)
CUSTOM_SSL_CERT_PATHPath to a combined PEM (certificate chain + private key) to serve instead of the default certificate. Read-only: served verbatim and never overwritten; an unreadable or malformed file fails startup
SKIP_SSL_CERT_DOWNLOADSet to 1 to skip the certificate download entirely (no network access). With no cached or custom cert the server generates a self-signed one — connect with insecure_mode=True
SNOWFLAKE_API_ENDPOINTEndpoint the emulator advertises to clients, e.g. https://sf.example.com:4566 — needed behind a custom domain
SF_S3_ENDPOINT_EXTERNALhost:port the emulator advertises to clients for stage uploads and downloads
SF_HOSTNAMESComma-separated hostnames that route to the emulator. Setting it replaces the built-in list rather than extending it, and a request whose Host matches no entry is rejected — include localhost if your clients use it. The first entry also supplies the advertised API host when SNOWFLAKE_API_ENDPOINT is unset
SF_LOGLog level: trace, debug, info, warn, error, off (a level, not a log-file path)
DEBUGSet to 1 for debug logging; SF_LOG wins when both are set
RUST_LOGFull tracing env-filter directive, e.g. snowflake_server=debug,tower_http=trace; wins over SF_LOG and DEBUG
DISABLE_EVENTSSet to 1 to disable telemetry

Tags

TagContents
latestNewest build — tracks the main branch
X.Y.ZImmutable release build, e.g. 0.1.0 — pin it for a reproducible environment

Both linux/amd64 and linux/arm64 are published.

Security

⚠️ The emulator does not authenticate clients. Any user name and password is accepted, key-pair JWTs are not verified, and object privileges are not enforced. Anyone who can reach its port can read, modify, or drop every database in it — do not expose it beyond a trusted network, and do not load production data into it.

Keep the port on loopback (-p 127.0.0.1:4566:4566, as in the examples above); a plain -p 4566:4566 publishes on every interface. To share one instance, put access control in front of it — an SSH tunnel (ssh -N -L 4566:127.0.0.1:4566 user@remote-host), a private network, or a firewall allowlist — rather than opening the port.

Support

To get in touch with LocalStack to report issues and request new features, reach out on the following channels:

License

© 2026 LocalStack - All Rights Reserved

The LocalStack for Snowflake image is proprietary software and is subject to the LocalStack terms and conditions. Unauthorized use, reproduction, or distribution is prohibited.

Tag summary

Content type

Image

Digest

sha256:d24f3070d

Size

260.7 MB

Last updated

about 5 hours ago

docker pull localstack/snowflake-next