Skip to main content
Each Firebolt engine accepts SQL over an HTTP endpoint: a client sends an HTTP POST whose body is a single SQL statement, and the engine returns the result in the response body. Any HTTP client works. This page describes that wire protocol: request format, output formats, session handling, transactions, and security. For the endpoints you send to, the instance gateway or an engine’s own Service, see Connect to engines. The examples here reach an engine directly through its Service, so forward its port to your workstation:
kubectl -n firebolt port-forward svc/my-engine-service 3473:3473
Then submit a query:
curl --silent "localhost:3473" --data-binary "SELECT 42"
# 42

System settings

Set system settings per query by appending them to the HTTP query string. For example, set timezone:
curl --silent "localhost:3473/?timezone=utc" --data-binary "SELECT TIMESTAMPTZ '1996-09-03 11:19:33.123456 Europe/Berlin' AS ts"
# ts
# timestamptz
# 1996-09-03 09:19:33.123456+00
Separate multiple settings with an ampersand (&):
curl --silent "localhost:3473/?max_result_rows=1&timezone=utc" --data-binary "SELECT 1"

Output format

Results are returned in the response body. By default they are a human-readable tab-separated string:
curl --silent "localhost:3473" --data-binary "SELECT x, 42 * x AS multiplied FROM generate_series(1,4) g(x)"
x	multiplied
int	int
1	42
2	84
3	126
4	168
Set the output_format query-string parameter to choose another format. Use JSON_Compact when results are consumed by code rather than read by a human. The supported formats are:
  • TabSeparatedWithNamesAndTypes (default)
  • JSON_Compact
  • JSON_CompactLimited (same as JSON_Compact, capped at 10,000 rows)
  • JSONLines_Compact (chunked version of JSON_CompactLimited)
JSON_Compact returns one JSON document:
curl --silent "localhost:3473/?output_format=JSON_Compact" --data-binary "SELECT x, 42 * x FROM generate_series(1,4) g(x)"
{
        "query":
        {
                "query_id": "7487991c-d84c-40a4-bdaf-3bc4507f250a",
                "request_id": "a6a9f32d-8b3c-469e-a778-1ff27221781b",
                "query_label": null
        },
        "meta":
        [
                { "name": "x", "type": "int" },
                { "name": "?column?", "type": "int" }
        ],
        "data":
        [
                [1, 42],
                [2, 84],
                [3, 126],
                [4, 168]
        ],
        "rows": 4,
        "statistics":
        {
                "elapsed": 0.001598,
                "rows_read": 1,
                "bytes_read": 1,
                "time_before_execution": 0.000324689,
                "time_to_execute": 0.000205699,
                "scanned_bytes_cache": 0,
                "scanned_bytes_storage": 0
        }
}
JSONLines_Compact returns newline-delimited messages:
curl --silent "localhost:3473/?output_format=JSONLines_Compact" --data-binary "SELECT x, 42 * x FROM generate_series(1,4) g(x)"
{"message_type":"START","query_id":"7487991c-d84c-40a4-bdaf-3bc4507f250a","query_label":null,"request_id":"a6a9f32d-8b3c-469e-a778-1ff27221781b","result_columns":[{"name":"x","type":"integer"},{"name":"?column?","type":"integer"}]}
{"message_type":"DATA","data":[[1,42],[2,84],[3,126],[4,168]]}
{"message_type":"FINISH_SUCCESSFULLY","statistics":{"bytes_read":1,"elapsed":0.001598,"result_rows":4,"rows_read":1,"scanned_bytes_cache":0,"scanned_bytes_storage":0}}

Sessions

The protocol is stateless: the engine keeps no server-side session. Most statements need nothing more than a single request, but operations that carry state across statements, such as changing the current database or running an explicit transaction, need the client to maintain that state. The engine drives this through response headers and query-string parameters:
  • When a response carries Firebolt-Update-Parameters: key=value, include key=value in the query string of every later request on the same connection.
  • When a response carries Firebolt-Remove-Parameters: key, drop key from the query string of later requests.

Changing the current database

USE DATABASE validates that the database exists and returns a Firebolt-Update-Parameters: database=... header. Because there is no server-side state, the change takes effect only once you start sending that parameter:
curl --silent "localhost:3473" --data-binary "SELECT current_database()"
# firebolt
curl --verbose "localhost:3473" --data-binary "USE DATABASE example"
# < Firebolt-Update-Parameters: database=example
curl --silent "localhost:3473" --data-binary "SELECT current_database()"
# still firebolt: the returned parameter has not been applied yet
curl --silent "localhost:3473/?database=example" --data-binary "SELECT current_database()"
# example

Explicit transactions

BEGIN TRANSACTION returns a Firebolt-Update-Parameters: transaction_id=... header. Send that transaction_id on every later request to run inside the transaction. COMMIT or ROLLBACK returns Firebolt-Remove-Parameters: transaction_id, after which you stop sending it. See Explicit transactions.
curl --verbose "localhost:3473" --data-binary "BEGIN TRANSACTION"
# < Firebolt-Update-Parameters: transaction_id=0000000000000c04ba100
curl --silent "localhost:3473/?transaction_id=0000000000000c04ba100" --data-binary "INSERT INTO t1 VALUES (1)"
curl --verbose "localhost:3473/?transaction_id=0000000000000c04ba100" --data-binary "COMMIT TRANSACTION"
# < Firebolt-Remove-Parameters: transaction_id

Transactions

Every statement runs in its own transaction that commits when the statement finishes and rolls back when it fails. There can be any number of concurrent read transactions, but only one write transaction can be active across the whole engine at a time. Submitting a write while another write transaction is active returns an error, so a client that issues concurrent writes serializes them itself, for example through a queue.

Security

A Firebolt engine’s HTTP endpoint has no built-in authentication or transport security:
  • Traffic is unencrypted HTTP. Anyone who can observe it reads everything exchanged, including secrets passed to reach external resources such as S3 or GCS.
  • Requests are not authenticated and there is no role-based access control. Anyone who can reach the endpoint has full access to the engine.
Treat network reachability as the security boundary. Restrict access to the gateway and engine Services with Kubernetes NetworkPolicies and your platform’s network controls, and terminate TLS at an ingress in front of the deployment when clients connect from outside the cluster. See Security for the Firebolt Operator and the Helm chart.

Other ways to connect

Firebolt CLI

The fb CLI (download from the releases page) speaks the same HTTP protocol. The --core preset targets localhost:3473 with no authentication, which matches a port-forwarded engine endpoint:
fb --core
=> SELECT 42;
 ?column?
---------
       42
Pass --host <hostname> to connect to a different host, or a query as a positional argument to run it and exit (fb --core 'SELECT 42').

Client SDKs

Firebolt’s client SDKs connect to a self-managed engine over the same protocol. See the connection guide for each:

Web UI

A built-in web UI is available as an optional engine sidecar. See Web UI.