flinksql-studio
A zero-dependency, single-file browser IDE for Apache Flink SQL — built for streaming engineers.
2.4K
A zero-dependency, modular browser IDE for Apache Flink SQL — built for engineers who want a real query interface without leaving their laptop.
FlinkSQL Studio is a self-hosted web IDE that connects to the Flink SQL Gateway and lets you:
flinksql-studio/
│
├── index.html # Entry point — HTML structure + modal markup only (no inline logic)
│
├── css/
│ ├── theme.css # CSS variables: dark, light, monokai, dracula, nord, contrast
│ ├── layout.css # Connection screen, topbar, sidebar, editor, results, statusbar
│ └── panels.css # Performance panel, Job Graph panel, Node Detail modal
│
├── js/
│ ├── state.js # Global state, constants (MAX_ROWS), SNIPPETS library, api()
│ ├── connection.js # Connect screen: modes, auth, doConnect(), heartbeat, tips modal,
│ │ # admin session, existing session loader, session renewal
│ ├── tabs.js # Tab add / rename / switch / close
│ ├── editor.js # SQL editor: line numbers, format, Ctrl+/ comment, keyboard shortcuts
│ ├── execution.js # runSQL(), pollOperation(), duplicate submission guard, job tagging
│ ├── results.js # Result table render, pagination, CSV export, stream slot selector
│ ├── log.js # Log panel, operations list, query history, error parsing
│ ├── catalog.js # Catalog browser: refresh, tree render, table detail
│ ├── session.js # Session CRUD, job scoping, cancel confirmation, audit trail,
│ │ # admin session detail inspector, duplicate guard helpers
│ ├── perf.js # KPIs, sparklines, gauges, checkpoints, cluster resources, reports
│ ├── theme.js # Theme select, applyTheme(), persist
│ ├── workspace.js # Workspace export/import JSON, restoreWorkspace()
│ ├── modals.js # Error modal, job list, cancelSelectedJob(), admin sessions overview
│ ├── jobgraph.js # DAG render, zoom/pan, node detail, live metrics, vertex timeline
│ ├── timeline.js # Vertex status timeline chart (Gantt-style)
│ ├── misc.js # togglePerfLive(), filterPerfQueries(), init
│ └── admin.js # Admin badge, Sessions button, report UI, Flink docs links,
│ # query count hook, launchApp/disconnectAll patch
│
├── docs/
│ ├── index.html # Documentation site
│ ├── demo-datagen-kafka.sql # Simple demo pipeline
│ └── full-pipeline.sql # Full multi-node pipeline
│
├── nginx/studio.conf # nginx reverse proxy config
├── scripts/
│ ├── setup.sh / setup.ps1 # Quickstart scripts
│ └── download-connectors.sh/.ps1 # Auto-download matching connector JARs
├── k8s/
│ ├── manifests/deployment.yaml
│ └── helm/flinksql-studio/
├── Dockerfile
├── docker-compose.yml
├── CONTRIBUTING.md
├── LICENSE
└── README.md
git clone https://github.com/coded-streams/flinksql-studio
cd flinksql-studio
docker compose up -d
open http://localhost:3030
On first connect, a Tips & Concepts modal walks you through the IDE and key Flink concepts — with SQL code examples for every tip.
| Mode | When to use | Auth |
|---|---|---|
| Via Studio | Local Docker — routes through nginx at localhost:3030 | None |
| Direct Gateway | Remote clusters, Confluent Cloud, AWS Managed Flink | Bearer token or Basic |
| 🛡 Admin Session | Platform operators — full cluster visibility, professional reports | Passcode |
Test Connection first — the IDE auto-fetches existing sessions from the gateway and populates a dropdown so you can reconnect without copy-pasting UUIDs.
Connect using the 🛡 Admin button on the connect screen and enter the admin passcode (admin1234 by default — change it immediately after first login via the 🛡 badge in the topbar).
| Feature | Regular Session | Admin Session |
|---|---|---|
| Jobs visible in Job Graph | Own session jobs only | All cluster jobs |
| Cancel job | Own jobs only | Any job on cluster |
| Session Inspector | — | Full cross-session breakdown |
| Audit trail | — | Timestamped log of admin actions |
| Report type | Standard session report | Technical or Business/Management |
When connected as admin, the Sessions panel (sidebar) and the 🛡 Sessions topbar button both show all registered sessions with live counts:
Click 🔍 Inspect on any session to open the Session Inspector — a tabbed modal showing:
Every admin action records:
🛡 John Smith — Cancel Job at 14:32:07
🛡 John Smith — Session Deleted at 14:35:12
This notice appears on the session card in the sidebar so any user reconnecting to that session can see what changed and when.
From Performance → Report, admin sees two report type options:
| Report Type | Audience | Content |
|---|---|---|
| Technical Report | Engineering teams | Vertex-level metrics, JVM heap, checkpoint durations, per-session job breakdown, exact SQL statements |
| Business / Management Report | Non-technical stakeholders | Self-explaining resource utilisation %, job health summaries, throughput in plain language, no SQL or technical jargon |
Both reports carry the admin's name, session ID, and generation timestamp in the header.
pipeline.name SET before every INSERT.Connector JARs must match your Flink version exactly. Wrong version → NoClassDefFoundError: guava30/.../Closer on every INSERT job.
| Flink version | Kafka connector JAR |
|---|---|
| 1.20.x | flink-sql-connector-kafka-3.3.0-1.20.jar |
| 1.19.x ← recommended | flink-sql-connector-kafka-3.3.0-1.19.jar |
| 1.18.x | flink-sql-connector-kafka-3.3.0-1.18.jar |
| 1.17.x | flink-sql-connector-kafka-3.2.0-1.17.jar |
| 1.16.x | flink-sql-connector-kafka-3.1.0-1.16.jar |
# Auto-detect version and download:
./scripts/download-connectors.sh
# Or Windows:
.\scripts\download-connectors.ps1
CREATE TABLE kafka_events (
event_id STRING,
user_id STRING,
amount DOUBLE,
event_time TIMESTAMP(3),
WATERMARK FOR event_time AS event_time - INTERVAL '5' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'user-events',
'properties.bootstrap.servers' = 'kafka-01:29092',
'properties.group.id' = 'flink-consumer-01',
'scan.startup.mode' = 'latest-offset',
'format' = 'json'
);
Requires: flink-sql-avro-confluent-registry-<ver>.jar and flink-sql-avro-<ver>.jar in /opt/flink/lib/.
CREATE TABLE payments_avro (
payment_id STRING,
amount DOUBLE,
currency STRING,
ts TIMESTAMP(3),
WATERMARK FOR ts AS ts - INTERVAL '3' SECOND
) WITH (
'connector' = 'kafka',
'topic' = 'payments',
'properties.bootstrap.servers' = 'kafka-01:29092',
'properties.group.id' = 'flink-payments-01',
'format' = 'avro-confluent',
'avro-confluent.url' = 'http://schemaregistry0-01:8081',
'scan.startup.mode' = 'earliest-offset'
);
-- 1. Enable checkpointing to S3/MinIO
SET 'state.backend' = 'filesystem';
SET 'state.checkpoints.dir' = 's3://flink-checkpoints/cp';
SET 'execution.checkpointing.interval' = '10000';
-- 2. Sink results to data lake (Parquet, partitioned)
CREATE TABLE trade_archive (
trade_date STRING,
symbol STRING,
volume DOUBLE,
total_usd DOUBLE
) PARTITIONED BY (trade_date)
WITH (
'connector' = 'filesystem',
'path' = 's3://my-data-lake/trades/',
'format' = 'parquet',
'sink.rolling-policy.rollover-interval' = '10 min',
'sink.partition-commit.delay' = '1 min',
'sink.partition-commit.policy.kind' = 'success-file'
);
For MinIO, add these to your Flink config:
fs.s3a.endpoint: http://minio:9000
fs.s3a.access-key: minioadmin
fs.s3a.secret-key: minioadmin
fs.s3a.path.style.access: true
Register a Java/Python UDF that calls your model endpoint (SageMaker, Vertex AI, custom FastAPI):
-- Register UDF (JAR must be in /opt/flink/lib/)
CREATE FUNCTION predict_risk AS 'com.mycompany.flink.RiskScoringUDF';
-- Use inline in pipeline — scores every record in real time
SELECT
trade_id,
symbol,
amount,
predict_risk(symbol, amount, volume, volatility) AS risk_score
FROM enriched_trades_source
WHERE predict_risk(symbol, amount, volume, volatility) > 0.75;
-- Flink: compute and publish features
INSERT INTO ml_features_kafka
SELECT
user_id,
COUNT(*) AS txn_count_5m,
SUM(amount) AS total_spend_5m,
MAX(amount) AS max_txn_5m,
window_end AS feature_time
FROM TABLE(HOP(TABLE transactions, DESCRIPTOR(event_time),
INTERVAL '1' MINUTE, INTERVAL '5' MINUTE))
GROUP BY user_id, window_start, window_end;
-- Python AI service consumes 'ml-features', runs model.predict(),
-- publishes predictions back to 'ml-predictions' topic
-- Flink: join predictions back for downstream actions
SELECT s.user_id, s.amount, p.fraud_score, p.recommendation
FROM transactions s
JOIN predictions_source p
ON s.user_id = p.user_id
AND p.ts BETWEEN s.event_time - INTERVAL '10' SECOND
AND s.event_time + INTERVAL '10' SECOND;
Run this at the start of every Flink SQL session (available as a snippet under CONFIG → ⚡ Recommended Streaming Config):
SET 'execution.runtime-mode' = 'streaming';
SET 'parallelism.default' = '2';
SET 'execution.checkpointing.interval' = '10000';
SET 'execution.checkpointing.mode' = 'EXACTLY_ONCE';
SET 'table.exec.state.ttl' = '3600000';
SET 'table.exec.source.idle-timeout' = '10000';
SET 'table.exec.mini-batch.enabled' = 'true';
SET 'table.exec.mini-batch.allow-latency' = '500 ms';
SET 'table.exec.mini-batch.size' = '5000';
SET 'table.optimizer.agg-phase-strategy' = 'TWO_PHASE';
Browser (localhost:3030)
│
▼
[nginx: flink-studio container]
│ /flink-api/ → flink-sql-gateway:8083
│ /jobmanager-api/ → flink-jobmanager:8081
▼
[Flink SQL Gateway] ←→ [JobManager / TaskManagers]
│
[Kafka / Schema Registry / MinIO / Elasticsearch]
Ctrl+Enter run, Ctrl+S save, Ctrl+/ comment, selection-only runFlinkSQL Studio auto-saves tabs to localStorage. For permanent backup across machines:
crypto-pipeline)To resume: ↑ Import Workspace → select your .json file.
Flink sessions are ephemeral — the export saves your scripts, not the running session. After importing, re-run your
USE CATALOGandCREATE TABLEstatements.
| What | Value |
|---|---|
| Internal Kafka bootstrap | kafka-01:29092 |
| Schema Registry | http://schemaregistry0-01:8081 |
| Kafka UI | http://localhost:28040 |
| Flink UI | http://localhost:8012 |
pipeline.name SET injected before INSERT with session label prefixSee CONTRIBUTING.md for details.
MIT — see LICENSE. Created by Nestor Martourez. A · codedstreams
Content type
Image
Digest
sha256:bca0e5556…
Size
21 MB
Last updated
4 months ago
docker pull codedstreams/flinksql-studio:sha-00a2d28