Snowflake Snowpipe Streaming
Stream records into Snowflake in near real time via the Snowpipe Streaming high-performance architecture. Records become queryable in the target table within seconds of being written, with no intermediate files and no warehouse required for ingest.
Prerequisites
- A Snowflake account on a supported region (high-performance architecture is GA on AWS, Azure, and GCP commercial regions).
- A Snowflake user dedicated to Monad ingest, with key-pair auth enabled.
- A role with
USAGEon the database/schema,INSERTon the target table, andOPERATE/MONITORon the pipe. - A target table with columns matching the JSON keys you stream.
- A STREAMING pipe (
CREATE PIPE ... DATA_SOURCE = (TYPE = 'STREAMING')) pointing at that table. - The Monad node must be able to reach
*.snowflakecomputing.comover HTTPS.
Setup Instructions
Step 1: Generate an RSA key pair
Generate an unencrypted PKCS#8 RSA key pair locally:
Code
Keep monad_key.pem private — you'll paste it into Monad as a secret. The contents of monad_key.pub get registered on the Snowflake user.
See Key-pair authentication and key-pair rotation for details, including rotation procedure.
Step 2: Create the Snowflake user and role
Run these as a role with SECURITYADMIN or higher:
Code
The connector signs JWTs that do not carry a role claim. The user's
DEFAULT_ROLEis what Snowflake uses to authorize the request, so it must point at the role that owns the grants below.
Step 3: Create the target table
The table schema must match the JSON shape you're streaming. For semi-structured ingest, a single VARIANT column works well:
Code
For typed columns, define them explicitly and ensure your upstream pipeline emits matching keys.
Step 4: Create the STREAMING pipe
The pipe is the ingest target the connector writes to. It must be created with DATA_SOURCE = (TYPE = 'STREAMING'):
Code
For a typed schema, replace MATCH_BY_COLUMN_NAME with an explicit column list. See CREATE PIPE.
Step 5: Grant the role access
Code
Step 6: Configure the output in Monad
In the pipeline editor, add the Snowflake Snowpipe Streaming output and fill in the settings below.
Configuration
Settings
| Setting | Type | Required | Description |
|---|---|---|---|
| Account | string | Yes | Snowflake account identifier, in the form orgname-account_name (e.g. acme-prod1). This is the same identifier you use in the Snowflake URL. |
| User | string | Yes | The Snowflake user for key-pair auth. Its DEFAULT_ROLE must be a role with access to the pipe. |
| Database | string | Yes | Database containing the pipe. Alphanumeric and underscores only. |
| Schema | string | Yes | Schema within the database that contains the pipe. Alphanumeric and underscores only. |
| Pipe | string | Yes | Name of the pre-existing STREAMING pipe. Alphanumeric and underscores only. |
| Channel Prefix | string | No | Prefix used for channel names. Final channel names are {prefix}_{uuid}_{i}, where uuid is a fresh random identifier. And i ranges over the channel pool. Defaults to monad. |
| Private Key | secret | Yes | RSA private key (PEM) for the user. Either raw PEM or base64-encoded PEM is accepted. |
| Batch Config | object | No | Controls when a batch is flushed to Snowflake. See below. |
Batch tuning
| Field | Default | Min | Max | Notes |
|---|---|---|---|---|
| Records per batch | 10,000 | 1 | 50,000 | Soft cap; flush also fires on size/time. |
| Batch size (bytes) | 2 MiB | 1 MiB | 3.5 MiB | Snowflake caps each appendRows body at 4 MiB; we stay below that to leave headroom for JSON framing. |
| Publish rate (seconds) | 10 | 1 | 60 | Maximum time a partial batch waits before being flushed. |
The connector picks the parallel channel count from the configured batch size: smaller batches get more parallel channels (up to 32) to keep per-second throughput up; larger batches use fewer channels since each one already moves more bytes per request. You don't tune this directly — choose the batch size that matches your freshness/throughput goals and the channel pool sizes itself.
Debugging
Status checks in Snowflake
Do not use
SYSTEM$PIPE_STATUS— that's the classic Snowpipe function and its fields (pendingFileCountetc.) don't apply to streaming pipes.
For the high-performance architecture, use:
Code
COPY_HISTORY does not record successful Snowpipe Streaming row inserts — they commit directly into the table. It only surfaces parse/load errors. An empty COPY_HISTORY result means no errors, not no traffic.
See INFORMATION_SCHEMA functions for the full set.
Confirming rows landed
Code
If Monad reports append rows ok but the row count isn't climbing, run SHOW CHANNELS IN PIPE … and check last_committed_offset_token — if it's advancing but the table is empty, the schema mismatch is silently dropping rows.
Troubleshooting
Common Issues
snowflake 408: stream timeout— Snowflake received the bytes but couldn't commit them inside its server-side ack window. Usually the pipe is congested. Retries are safe (continuation tokens make appends idempotent). If sustained, drop concurrent writers against this pipe or shard to a second pipe.Client.Timeout exceeded while awaiting headers— the HTTP client gave up before Snowflake responded. Check network latency from the Monad cluster to the ingest host; firewalls or NAT gateways are common culprits.JWT token is invalid/390144— the public key on the Snowflake user doesn't match the private key in Monad. Re-runDESC USERand verify theRSA_PUBLIC_KEYfingerprint matches.Insufficient privileges to operate on pipe— the user'sDEFAULT_ROLEdoesn't haveOPERATEon the pipe. The JWT carries no role claim, so workspace/session role overrides won't help — fixDEFAULT_ROLE.- No rows in the target table despite successful appends — usually a schema mismatch. Check
INFORMATION_SCHEMA.COPY_HISTORYforFIRST_ERROR_MESSAGE. continuation token mismatchfollowed by reopen — expected behavior when a request times out and the connector recovers. If frequent, treat as a symptom of pipe-side congestion.- Region mismatch — high-performance architecture is not yet available in every region. Confirm your account's region from the Snowpipe Streaming high-performance overview.
Best Practices
- One pipe per data shape, not one pipe per pipeline. Reuse pipes across pipelines whenever the target table is the same.
- Use semi-structured (
VARIANT) columns for schema-evolving sources like Cloudtrail. You can flatten downstream with views or dynamic tables. - Rotate keys at least annually. Snowflake supports two active public keys per user (
RSA_PUBLIC_KEYandRSA_PUBLIC_KEY_2) so you can rotate without downtime — see Key-pair rotation. - Monitor
PIPE_USAGE_HISTORYweekly to track credit consumption and ingestion latency trends.
Cost
Snowpipe Streaming high-performance ingest is billed on a serverless compute model — there is no warehouse to size. Costs vary by region, edition, and ingest volume. The current per-credit and per-feature rates are published in Snowflake's Credit Consumption Table (PDF). That document is the source of truth and is updated by Snowflake periodically; we do not mirror its rates here.
To see your actual usage, query:
Code
Related Articles
- Snowpipe Streaming high-performance architecture overview
- Snowpipe Streaming high-performance REST API reference
- CREATE PIPE
- Key-pair authentication
- INFORMATION_SCHEMA functions
- Credit Consumption Table (PDF)