Environments & Repository Sources

This page covers the deployment-target model, environments, groupings, connection configuration, transport/security options, and the on-demand repository/storage sync integration.

Environments

Environments are user-defined deployment targets with no hardcoded taxonomy. Model whatever your pipeline needs (Development, QA, Staging, Production, DR, UAT, Sandbox, Demo). The Environments page shows one card per environment with its approval requirement, the environment it runs after, how many connections it holds (counting those its groupings bring in) and how many groupings are assigned. Opening an environment lists every connection in it with its engine and host; a connection that a grouping brought in says through that grouping, and leaves when the grouping is removed. From there you can:

Every change is saved on the server before the page shows it. A refused change says which environment was not saved and why, for example "Staging" was not saved: That would make a loop: Staging after Production after Staging, and the page keeps the previous value. If the list cannot be loaded, the page says why and offers Retry.

Environments are stored in the platform database and persist across restarts; a fresh install is seeded with Development, Staging and Production, which you can rename or remove. Names are unique regardless of case and can be at most 50 characters. Adding or changing environments requires the Release Manager or Admin role; every role can view them.

Groupings

Groupings are logical clusters a connection can belong to, and unlike environment (one-to-one), a connection can be in multiple groupings. Model "all Postgres clusters", "tenant shard A", "us-east", etc., for set-wise deployment and reporting. Managed from the Groupings page (Release Manager or Admin; every role can view): each card shows how many connections the grouping holds and their database type, Add Grouping creates one, and opening a grouping offers Rename, Manage Connections and Delete. Groupings are stored in the platform database, so one with no members still persists. Names are unique regardless of case and can be at most 100 characters. Renaming cascades: every connection, environment and release that used the old name is updated in the same transaction, so membership is never orphaned. Deletion is blocked while any connection still belongs; deleting an unused grouping also removes it from any environment it was assigned to. Opening a grouping lists its connections with their engine, host, database and environment, click one to see that connection's details and test it without leaving the page. If the groupings cannot be loaded, the page says why and offers Retry; a refused change names the grouping and the reason.

Manage Connections opens Assign Connections: check a connection to add it, uncheck it to take it out. When the grouping is assigned to an environment, the dialog says so, because a grouping's connections belong to that environment:

One database type per grouping and per environment. A grouping is deployed as a unit and a script is sent to every target in an environment, so both are limited to a single dialect. The first connection sets the type; connections of any other dialect are then greyed out with the reason, both when assigning to a grouping and when adding to an environment, and a grouping whose dialect clashes cannot be added to an environment. The server enforces the same rule for every path (the API, bulk upload and connection edits), returning 409 with the reason. Simcha DB Studio does not translate a script between dialects, the script text is sent to each target as written, so a mixed environment would deploy Oracle syntax to a MySQL target and fail there.

A grouping that already mixes types (created before this rule) is flagged on its card and in its detail with the types it holds, and cannot be assigned to an environment until it is split. Removing the connections that do not belong is always allowed, so a mixed grouping can be corrected in place.

Connection Configuration

Each environment is backed by one or more connections. The Connections page shows a card per connection with its engine's brand mark and its host, database, environment and groupings, each named; empty values are left out. Opening a card shows the same values with Test, Consumers, Edit and Delete. Hide Demo Connections takes the built-in demo connections out of your view, and Show Demo Connections brings them back.

Add Connection opens a form of the same name: pick the database type, supply host, port, database and credentials, optionally choose groupings and an environment, optionally mark Read-Only Connection, check reachability with Test Connection (Connected. or Could not connect: <reason>), and save. A new connection needs a password, unless Test Connection connects without one, as it does for a Redis, MongoDB, Cassandra or Elasticsearch server that has no authentication. Edit opens Edit Connection, saved with Save Changes; the database type of a saved connection cannot be changed, so add a new connection for another engine. Every save names the connection and, when it is refused, the reason. Connections persist through the shared /api/connections endpoint, so the IDE and Database DevOps see one list, saving once enables both interactive querying and unattended deployment.

Bulk Upload

Import many connections at once with Bulk Upload on the Connections page: choose or paste a CSV or JSON file (a CSV template is downloadable from the dialog). Columns are name, type, host, port, database, username, password, environment, groupings, ssl; only name and type are required, and multiple groupings are separated with ;. Rows are validated in the browser for an instant preview and again server-side per dialect. The import button says how many connections it will add. Each row succeeds or fails independently, one bad row never blocks the rest; afterwards the dialog lists how many connections were added and every skipped row with its reason. Reachability is not required at import time, so hosts the server cannot reach yet still import; use Test on each afterwards. Passwords are encrypted at rest exactly as with a single create.

Import from the IDE

The Manager and IDE keep independent connection lists. Import (beside Add Connection) lists IDE connections not already configured here (Select All picks every one shown) and creates an independent copy; if the list cannot be loaded the dialog says why and offers Retry; targets you already hold are never offered and re-imports are skipped, so import cannot duplicate. The reverse (DevOps → IDE) is available from the IDE sidebar.

Deleting a connection keeps its execution history: past runs stay in Executions and Metrics with their scripts, status and timing, and simply no longer link to a connection.

Read-Only Connections

Marking a connection Read-Only Connection makes the server refuse INSERT/UPDATE/DELETE/DDL and change-script runs before they reach the database, while leaving reads, EXPLAIN, and schema browsing available. The block is enforced application-side on top of the account's own grants, protecting even privileged logins; such connections carry a Read-only badge. Writes are recognised in each engine's own language: SQL and CQL statements that change data or schema (including a Cassandra BATCH), MongoDB operations other than reads (and an aggregate with $out or $merge), Redis commands other than reads (CONFIG GET and CLIENT LIST are reads; CONFIG SET is not), Cypher with CREATE, MERGE, SET, DELETE, REMOVE or DROP or a procedure that is not a known read, and Elasticsearch operations other than search, count, get and index information.

Environment Color-Coding

Each connection's environment renders as a risk-tiered badge, production red, staging amber, development/test green, everywhere a connection's environment appears (Connections list, execution history). Matching is case-insensitive and prefix-based ("Production", "prod", "PROD-eu" all tier alike).

Advanced: TLS, Timeouts & Credentials

The Advanced section tunes how a SQL-engine connection (PostgreSQL, MySQL/MariaDB, SQL Server) is opened and run; engines that don't use a setting ignore it.

SSH Tunnel (Bastion / Jump Host)

SSH Tunnel reaches databases only accessible inside a private network. Supply the bastion host and port, SSH username, the bastion's SHA256 host key fingerprint (required: the bastion is checked against it before anything is sent), and an SSH password or private key (PEM, optional passphrase); the Host/Port fields then resolve from the bastion's perspective (typically the database's private address). The tunnel serves both interactive querying and unattended execution and is torn down on disconnect. SSH credentials are encrypted at rest and masked in API responses, like database passwords.

Idle Auto-Disconnect (Operator)

CONNECTION_IDLE_DISCONNECT_MIN closes pooled connections (and any backing SSH tunnel) after N minutes idle; it is required, and 0 disables. Server-wide, not per-connection.

Connection Security

Deployment Pipelines

Development -> QA -> Staging -> Production -> DR

At each stage the release deploys to that environment's connections, the team validates, an optional approval gate guards promotion, and the same release (same scripts, versions, hashes) advances, no inter-stage modification.

Repository & Storage Sources

Sync migration scripts on demand from source control and object stores. Open Repo Sources in the Database DevOps navigation and choose Add Source: pick the provider, supply credentials, set Release Scripts Path, Ad-hoc Scripts Path and File Pattern, then Test Connection (Connected to ... or Could not connect: <reason>) and Add Source. Edit opens Edit Source, saved with Save Changes. Each card names the provider, branch and file pattern; opening a source shows its paths and the last pull in words, for example Last pull succeeded with when and what it did. Deleting a source keeps the scripts already pulled from it. Adding, editing and deleting sources requires the Admin role; any role that can create scripts can test a source and pull from it.

Credentials (tokens, app passwords, secret keys, connection strings, service-account JSON, external IDs) are encrypted at rest and returned masked. When you edit a source, leaving a masked field untouched keeps the stored secret, so you can change a path or pattern without re-entering the token.

Source Control

ProviderAuthConfig
GitHubPAT (repo scope) or OAuth tokenowner/name, branch (default main)
GitLabPAT (read_repository)numeric Project ID, branch
BitbucketAtlassian account email and API token with Bitbucket scopes (repository read)workspace/repo slug, branch
Azure DevOpsPAT (Code Read)org, project, repo, branch

Object Storage

ProviderAuthConfig
AWS S3Access keys; or an IAM role ARN assumed via STS; or blank keys to use the ambient AWS credential chain (EC2/ECS role)bucket, region, prefix
Azure BlobConnection Stringcontainer, prefix
Google Cloud StorageService account key JSON; the account needs only Storage Object Viewer on the bucketbucket, prefix
DropboxApp key, app secret and OAuth2 refresh token (renewed automatically); or a short-lived access tokenroot folder

Path & Pattern Model

Each source scopes two folders, Release Scripts Path (e.g. db/migrations/release) and Ad-hoc Scripts Path (e.g. db/migrations/adhoc), and a File Pattern. Subfolders are always included. Separate several patterns with commas (*.sql, *.js); matching ignores case. A pattern without / matches the file name anywhere below the folder; a pattern containing / matches the path inside the folder, and ** spans any number of subfolders (**/migrations/*.sql). Leave the pattern blank for *.sql.

On-Demand Sync

Open a source under Repo Sources and choose Pull Scripts. Choose the Type, Release (scripts join releases) or Ad-hoc (scripts run on their own), and the Environment of the new scripts, which every script needs. Optionally choose the Instance (only that environment's instances are listed, and when the source's file pattern names one kind of script, such as *.sql, only the instances that can run it, as the note under the field says) and its Database, which starts on the instance's own database; override the Branch (source-control providers) or the Path, which shows the source's path for the chosen type, or The whole source when none is set; and pull. Every matching file is imported as a Pending script named by its path inside the pulled folder, placed in that environment and target, and tagged with the provider, source name and mode. There is no background poll.

Pulls are incremental. Each imported script remembers its source file and a SHA-256 hash of its content, so pulling again skips files that have not changed, updates the script when a file changed (resetting it to Pending so the new content is reviewed; the script keeps its environment and target), and imports files that are new. The result reports imported, updated, unchanged and failed counts. A file that cannot be read is listed with its error and does not stop the rest of the pull. Pulling from an inactive source is refused.

Script Formats by Engine

Pulled or uploaded scripts are classified by extension first, then by content, and can only run against a compatible connection.

EngineExtensionHow the script runs
PostgreSQL, CockroachDB, TimescaleDB.sqlSplit on ;; $$ function bodies stay whole.
MySQL, MariaDB.sqlSplit on ;; DELIMITER lines change the separator for procedures and triggers.
SQL Server.sqlEach GO batch runs whole.
Oracle.sqlSplit on ;; PL/SQL blocks (BEGIN, DECLARE, CREATE ... PROCEDURE/FUNCTION/TRIGGER/PACKAGE) end at a line holding only /.
SQLite.sqlSplit on ;; trigger bodies run to their END;.
MongoDB.jsmongosh-style db.<collection>.<method>(...) calls with literal arguments (inserts, updates, deletes, indexes, aggregate, bulkWrite, createCollection, createView, runCommand), plus ISODate, ObjectId, NumberDecimal/Int/Long and simple const/let values. Other JavaScript is rejected with the line number.
Redis.redisOne command per line; # and // lines are comments.
Cassandra.cqlSplit on ;; BEGIN BATCH ... APPLY BATCH runs as one statement.
Neo4j.cypher, .cypSplit on ;.
Elasticsearch.jsonA JSON operation or array of operations (index create/delete, mappings, aliases, index, bulk, update, delete, update/delete by query, search, count, get). Bulk item errors fail the step.

Comments are ignored when splitting, including separators that appear inside comments or quoted strings.

Failure Modes