If you’ve worked with SQL Server Database Projects in a traditional CI/CD setup, you’ve probably solved the “which environment am I deploying to?” problem with SQLCMD variables. You define an $(Environment) variable, set it to DEV, TEST, or PROD in separate publish profiles, and branch on it in your post-deployment script. Simple and reliable.
Then you move to SQL database in Microsoft Fabric, and that pattern stops working.
The problem
Fabric SQL database comes with built-in Git integration and deployment pipelines. Under the hood it still uses a SQL project (.sqlproj), but Fabric owns that file. Any manual edits you make to the .sqlproj in your repository are reset the next time Fabric commits to source control. There’s no publish profile to edit either, because you’re not running sqlpackage yourself. Fabric does the deployment for you.
That means no custom SQLCMD variables and no easy way to tell your scripts which environment they’re running in.
The good news is that Fabric now supports pre- and post-deployment scripts as part of its built-in CI/CD. You create a query under Shared Queries, open its menu, and select Set as Post-deployment Script. From then on, it runs automatically whenever the database is updated from Git or deployed through a deployment pipeline.
So we have a hook that runs on every deployment. What we still need is a way for that script to figure out where it’s running.
Asking the database where it lives
Every environment in Fabric typically lives in its own workspace: one for dev, one for test, one for prod. If the database can tell us which workspace it belongs to, we can branch on it.
It turns out it can. Let’s see what SERVERPROPERTY('ServerName') returns in a Fabric SQL database:
sql
SELECT SERVERPROPERTY('ServerName') AS ServerName;
The result looks something like this:
3f7a1c92-5b4e-4d8a-9c21-7e6f0b8d4a15-a91d4e27-0c6b-4f3e-8b75-2d9c1e6f8a03.database.fabric.com
The server name is made up of two GUIDs joined by a hyphen, followed by the .database.fabric.com suffix:
<tenant-id>-<workspace-id>.database.fabric.com
3f7a1c92-5b4e-4d8a-9c21-7e6f0b8d4a15 - a91d4e27-0c6b-4f3e-8b75-2d9c1e6f8a03 .database.fabric.com
└──────────── Tenant ID ─────────────┘ └─────────── Workspace ID ────────────┘
The first GUID is your Microsoft Entra tenant ID. It’s the same for every database in your organization, so it’s useless for telling environments apart. The second GUID is the ID of the Fabric workspace the database lives in, and that’s exactly the environment fingerprint we’re after.
Tip: To find out which workspace ID belongs to which environment, open each workspace in the Fabric portal and look at the URL: app.fabric.microsoft.com/groups/<workspace-id>/.... That’s the same GUID you’ll see in the server name.
Extracting the workspace ID
Rather than comparing the full server name string, extract the workspace ID. Each GUID is 36 characters long, so the tenant ID occupies positions 1 to 36, and the workspace ID starts at position 38 (after the separating hyphen):
sql
DECLARE @server NVARCHAR(256) = CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256));
SELECT
LEFT(@server, 36) AS TenantId,
SUBSTRING(@server, 38, 36) AS WorkspaceId;
Branching in the post-deployment script
Now you can write a post-deployment script that behaves differently depending on the workspace:
sql
DECLARE @workspaceId CHAR(36) =
SUBSTRING(CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)), 38, 36);
IF @workspaceId = 'a91d4e27-0c6b-4f3e-8b75-2d9c1e6f8a03'
BEGIN
PRINT 'Production workspace detected';
-- Production-only logic
END
ELSE IF @workspaceId = '5c2e8b14-9f7a-4d61-a3c8-0e4b7d2f9a6c'
BEGIN
PRINT 'Test workspace detected';
-- Load test data, enable diagnostics, etc.
END
ELSE
BEGIN
PRINT 'Development or unknown workspace';
-- Safe default behavior
END
Notice the ELSE branch. It matters more than it looks, as we’ll see below.
Things to watch out for
Workspace IDs are not permanent. If a workspace is deleted and recreated, it gets a new ID, and your script will silently fall into the ELSE branch. Keep that in mind when restructuring workspaces.
Branch-out creates new workspaces. Fabric’s “branch out to a new workspace” feature gives each feature branch its own workspace, each with its own ID. You can’t list these in advance, so make sure the fallback branch behaves safely. Treating unknown workspaces as development is usually the right call. Never let an unknown workspace fall through to production behavior.
Compare full GUIDs. It’s tempting to write LIKE '%a91d4e27%', but partial matching invites subtle mistakes. Extract the exact workspace ID and compare it with equality.
This relies on the server name format. Microsoft doesn’t document this format as a contract, so it could change in the future. Keep the parsing logic in one place so it’s easy to fix if it does.
A more durable alternative: a configuration table
If hard-coding workspace IDs feels brittle, there’s another approach that leans on a useful property of Fabric’s deployment model: it updates schema but leaves existing data in place.
Define a configuration table in your project so the schema is source-controlled:
sql
CREATE TABLE dbo.EnvironmentConfig (
ConfigKey NVARCHAR(50) NOT NULL PRIMARY KEY,
ConfigValue NVARCHAR(200) NOT NULL
);
Then, manually and once per workspace, insert the environment value:
sql
INSERT INTO dbo.EnvironmentConfig (ConfigKey, ConfigValue)
VALUES ('Environment', 'PROD');
This row lives only in that database. It isn’t in Git, and deployments won’t touch it. One important rule: don’t put this INSERT in your post-deployment script. The script runs identically everywhere, so it would overwrite your per-environment values.
Combining both approaches
You can also use both: read from the config table first, and fall back to the workspace ID if the table is empty. This handles freshly branched workspaces that haven’t been configured yet:
sql
DECLARE @env NVARCHAR(200) =
(SELECT ConfigValue FROM dbo.EnvironmentConfig WHERE ConfigKey = 'Environment');
IF @env IS NULL
BEGIN
DECLARE @workspaceId CHAR(36) =
SUBSTRING(CAST(SERVERPROPERTY('ServerName') AS NVARCHAR(256)), 38, 36);
SET @env = CASE @workspaceId
WHEN 'a91d4e27-0c6b-4f3e-8b75-2d9c1e6f8a03' THEN 'PROD'
WHEN '5c2e8b14-9f7a-4d61-a3c8-0e4b7d2f9a6c' THEN 'TEST'
WHEN 'e8b3f607-1d4c-4a92-b5e7-6c0a9f3d2b81' THEN 'DEV'
ELSE 'DEV'
END;
END
PRINT CONCAT('Deploying to: ', @env);
Wrapping up
Fabric’s managed Git integration takes away SQLCMD variables, but it doesn’t take away your ability to write environment-aware deployments. The server name of every Fabric SQL database follows the <tenant-id>-<workspace-id>.database.fabric.com pattern, which gives your scripts a reliable way to know which workspace they’re running in. Combine that with Fabric’s data-preserving deployments, which make a configuration table viable, and you have two solid building blocks. Pick the one that fits your workflow, or combine them, and make sure unknown environments always fall back to safe behavior.