Course 4 · Recipe 3 — The package asks the server
Some of what your deployment needs to know isn’t in your package and never will be. Which tenants are active on this server. Which feature flags are switched on right now. The next batch number to stamp. That state lives on the target, set by an app or an operator, changing without you — and you can’t hard-code it without baking a guess into the package and shipping it everywhere. So don’t guess. Ask.
The lever: a token that runs a query at deploy time
Section titled “The lever: a token that runs a query at deploy time”A script token usually holds a static value. But a token’s value can start with a tag that tells SchemaSmith to compute it at deploy time — and <*Query*> runs a SQL query against the target you’re deploying to, just before your scripts run:
"ScriptTokens": { "EnabledFeatures": "<*Query*>SELECT STRING_AGG(FlagName, ',') FROM FeatureFlag WHERE Enabled = 1"}Put it on the template, not the product — that way it resolves against the target database your deployment selected, not the server’s default database. Any script can then reference {{EnabledFeatures}} and get the live answer:
-- Record Active Features [ALWAYS].sql — [ALWAYS] runs on every quenchINSERT INTO DeployLog (ActiveFeatures) VALUES ('{{EnabledFeatures}}');The recipe: read the server, record what it said
Section titled “The recipe: read the server, record what it said”Say the server already has Billing and Reporting switched on, BetaSearch off. Deploy:
schemaquench --ConfigFile:deploy.settings.jsonSchemaSmith runs the query against the target, substitutes the result, and the after-script records it:
DeployLog → Billing,ReportingNow switch BetaSearch on at the server and quench again — same package, no edits:
DeployLog → Billing,Reporting BetaSearch,Billing,ReportingThe second deploy re-ran the query against the live server and recorded the new feature set. Nothing in the package changed. The package asked the server, and the server’s answer had changed.
The aha: ask, don’t assume — and fail before you act
Section titled “The aha: ask, don’t assume — and fail before you act”The shift here is direction. Recipes 1 and 2 pushed values from your metadata down into the schema. This one pulls a value up from the live target, at the moment of deploy, into a token every script can use. The package adapts to the server instead of carrying a stale copy of it.
And there’s a safety edge worth naming: if the query can’t run — wrong table, no permission, server unreachable — the deploy stops up front with a clear error, before any change is applied. You find out at the start, not halfway through a half-applied database. Want the full set of deploy-time tags — <*Query*>, <*QueryFile*> for queries in their own files, and the resolution order — the Script Tokens reference covers them all.
Check yourself: How can a deployment script use a value that only exists on the target server at deploy time?
Define the token with the <*Query*> (or <*QueryFile*>) tag — SchemaSmith runs that query against the actual target before substituting, so {{TokenName}} lands with live server data. If the query fails, the deploy stops up front rather than half-applying.
Think of it like checking the heat before you strike. You don’t assume the metal’s ready because it was ready last time — you read the color in this fire, right now, and shape to what you see. <*Query*> is that read: the package looks at the live server, takes its measure, and works from the truth on the anvil instead of a number it carried in from somewhere else.
Got a value you’re hard-coding per environment that really lives on the server — an active-tenant list, a feature toggle, a batch counter? Email me at forgebarrett@schemasmith.com — I read every one.
Next up: Course 4 · Recipe 4 — Assets that travel with the schema, where a logo and a reference dataset ride inside the package and land as the right binary literal on every engine.
Until then, may your package always ask before it acts, and the server’s answer always ring back true.
— Forge