Releases: fwdthinkers/sp_SQLFlightRecorder
Release list
sp_SQLFlightRecorder 1.1.3
[1.1.3] - 2026-08-27
Bug-fix release. @OutputFormat = N'Markdown' silently rendered only one
finding, regardless of how many the report produced. No behavior or contract
change otherwise: rule IDs, output columns, and the forward-only schema are
untouched, and the D-085 Markdown header keeps its 14 keys.
If you ran a Markdown report on 1.0.0 through 1.1.2 and acted on it,
re-run it. The findings you were shown were incomplete. The header's
Finding-Count and the Recommendation Summary were correct throughout, so a
saved report that shows Finding-Count: 32 above a single bullet is evidence
of this defect, not of a quiet server — the other 31 findings were evaluated
and then dropped at render time.
Fixed
Markdownoutput rendered exactly one finding of N (@Mode = 'Report',
@OutputFormat = 'Markdown'; all rules). The Findings body was built by
concatenating into a variable with anORDER BYover computedCASE
expressions — a construct SQL Server does not guarantee, and which in this
shape keeps only the last row in sort order. Because Informational sorts
last (D-068), the surviving row was almost always theFR_R0026
coverage summary. The render path now materialises the D-068 display rank
as a column and orders by it, so Markdown andFindingsOnlyreturn the same
findings in the same order by construction.@MinSeveritynever affected the symptom: the post-evaluation filter
(D-070) was always correct and#fr_findingswas always fully populated —
the rows were lost at render time, not at filter time. At
@MinSeverity = 'Critical'the Findings section would have been empty
entirely, since the Informational row that had been surviving is itself
filtered out.Default,FindingsOnly, andTimelineOnlywere never affected.
They emit plain result sets with no variable concatenation. Anyone using
those formats has complete output and needs to do nothing.
- The Markdown timeline used the same unguaranteed construct. It rendered
correctly (itsORDER BYused plain columns, which happens to survive), but
was one refactor away from the identical silent truncation. It now uses the
same materialised-rank approach.
Added
- CI assertion that the Markdown header counts match the rendered bodies
(ci-tier1):Finding-Countmust equal the number of rendered finding
bullets, andTimeline-Event-Countthe number of timeline bullets. Both
numbers derive from the same temp tables in the same code block, so any
disagreement is a defect by definition. The step previously asserted only
that the report's H1 was present, which is why this shipped. The check also
refuses to run against a fixture yielding fewer than two rows, where the
equality could not fail.
sp_SQLFlightRecorder 1.1.2
[1.1.2] - 2026-08-27
Documentation accuracy patch on 1.1.1, and a version-convention change
(D-201): from this release on, every release bumps the in-proc
ToolVersion and Build-Date-Utc — documentation-only releases included —
and a version/tag gate fails any tagged build whose artifact header does not
match the tag. This release therefore ships ToolVersion = 1.1.2 (build date
2026-08-27) with no behavior change. For the record: 1.1.1 shipped with
the artifact intentionally untouched, so its About output reports
ToolVersion 1.1.0 — that was the stated convention at the time, and this
release supersedes it.
Fixed
- Finding-field column names were wrong in the user guide
(docs/user-guide.md§13): the documented list includedFirstSeenUtcand
LastSeenUtc, which do not exist in the 16-column Findings contract
(D-067). The actual columns areStartTimeUtcandEndTimeUtc, and the
full 16-column list is now documented in contract order. If you scripted
against the old documented names, switch toStartTimeUtc/EndTimeUtc—
the result set itself never changed. Heuristicremoved from the documented evidence types
(docs/user-guide.md§13): it appears nowhere in the artifact and has never
been emitted. The closedEvidenceTypeset isObserved,Inferred.
(Confidence values remainHigh,Medium,Low, and severity values are
unchanged; the old docs listedHeuristicas an evidence type that did not
exist.)
Added
- Version/tag consistency gate —
scripts/check-version-tag.sh(D-201):
fails a tagged build when the artifact'sTool-Versionheader does not
match the tag. Wired intorelease.yml(replacing its inline check, same
behavior, single implementation) and into theci-tier1static-analysis
job, where it is a no-op on untagged builds. Locally runnable. - README: "How it fits with other SQL Server tools" section, and the missing
@TimeZoneparameter-table row (the parameter has existed since v1.0.0 but
was absent from the README table).
Changed
- README safety notes and all remaining hedged phrasing rewritten as verified
statements of fact: exact collector row caps (most collectors cap at
MaxRowsPerCollector; file stats atTOP (5000); perf counters at
TOP (100)over an 8-counter allow-list;FR_Configurationstores all of
sys.configurations; Query Store and schema activity cap per database
across up to 50 databases;@TopNvalidated 1–1000 while the
MaxRowsPerCollectorconfig key is not range-checked),@WhatIfpreview
behavior forPurge/Uninstall,@PreserveRunLog's timestamped
FR_RunLog_Archive_<yyyymmdd_hhmmss>rename, opt-in Agent job creation,
the per-collector capability-gated skip list, andReport's
repository-only evaluation (plus the fixed two-value capability probe that
runs on every invocation). - README lead reordered (what the tool is before the release note), the
Requirements heading reconciled with the SQL Server 2012 legacy row,
@Debugdocumented precisely (routesCollecttoCollectDebug, no
collector rows), repository file paths linked consistently, and a stray
horizontal rule removed.
sp_SQLFlightRecorder 1.1.0
[1.1.0] - 2026-08-26
Retention and repository-performance hardening (D-199). Root cause
addressed: when purge was not scheduled or not enforced, FR_* repository
tables grew without bound in real deployments (35M+ rows observed in
FR_SchemaActivity, 12M+ in FR_QueryStoreTopN) and Report ran for hours.
SQLFR must not silently become its own performance problem, so retention is
now operationally safe by default. ToolVersion is 1.1.0 (build date
2026-08-26); SchemaVersion advances to 0.5.0 (index-only DDL, forward-only
per D-038); RulePackVersion stays 0.4.3 (no rule logic or catalog change —
the Report changes below are access-path and evidence-cap work, not rule
behavior). Upgrades from 1.0.0 are in place: the first Install over an
existing repository builds the new indexes (one-time cost on large tables).
Added
- Post-collect purge step in the collector job (
@Mode = Install,
@CreateAgentJob = 1): theSQLFlightRecorder CollectAgent job now has two
steps —Collect, thenPurge(@WhatIf = 0) as normal cleanup. Existing
single-step jobs from earlier releases are upgraded in place (the step is
added and the Collect step is pointed at it). Job, step, and schedule
creation are idempotent: re-running Install never duplicates any of them. - Daily purge backstop job (
@Mode = Install,@CreateAgentJob = 1): a
second Agent job,SQLFlightRecorder Purge, runs
EXEC dbo.sp_SQLFlightRecorder @Mode = N'Purge', @WhatIf = 0;daily at
02:30 server time, protecting retention when the collector job is disabled,
changed, or failing before its cleanup step. Recorded inFR_Configas
PurgeAgentJobName/PurgeAgentJobCreatedBySQLFlightRecorder. - Retention/purge-support indexes (
@Mode = Install; theSchemaVersion
0.5.0DDL): a nonclusteredSnapshotIdindex on everyFR_Snapshotchild
table,IX_FR_Snapshot_RunId,IX_FR_RunLogStep_RunId, and
IX_FR_Request_QueryHash. Purge deletes verify child foreign keys per
deletedFR_Snapshotrow; without these indexes each check was a full
child-table scan, which is what made purge (and run-log cleanup, and
FR_QueryTextorphan cleanup) unusable on grown repositories. Created
idempotently on fresh installs and upgrades — the first Install over a large
old repository pays a one-time index build. - Retention guardrails (
@Mode = Configure):SnapshotRetentionDaysnow
accepts 1–31 andRunLogRetentionDays1–124; out-of-range values return a
cleanInvalidConfigValueerror andFR_Configis not updated. New tunable
RepositoryTableWarnRows(default 5,000,000) drives the Status size warning. - Status retention-health result set (
@Mode = Status; additive seventh
result setCheckName, CheckStatus, Detailper D-023): warns when the
oldest snapshot exceedsSnapshotRetentionDays, when purge appears not to
be keeping up (oldest data > retention + 2 days, with last-purge evidence),
when the collector job lacks a Purge step, when the daily purge job is
missing on Agent-capable platforms, and when anFR_*table exceeds
RepositoryTableWarnRows. msdb job checks are capability-gated and
permission-safe (Unknown, never an error). - Schema-activity evidence cap warning (
@Mode = Report, RuleId
FR_R0026_CoverageAndCapabilitySummary): when the window holds more
distinct schema/stats events than@MaxFindings, the timeline is capped and
one Informational Coverage finding says so and recommends narrowing the
window or reducing retention. - Scheduling guidance by platform —
docs/operations/scheduling.md. Which
scheduler to use is a capability question, not a preference: cron +sqlcmdon
Linux; a SQL Agent job step on Azure SQL Managed Instance (HasAgent = 1);
Azure Elastic Jobs or an external scheduler on Azure SQL Database, which has
neither Agent nor msdb. Includes copy-paste snippets and the all-platform
defaults (leaveCollectErrorLogandEnableBufferPoolCollectoroff unless
needed, periodicReport, scheduledPurge, UTC, and a documented uninstall
path).
Changed
-
Uninstall removes both Agent jobs (
@Mode = Uninstall): the collector
job and the daily purge job are dropped when this tool created them;
@WhatIf = 1previews both; already-missing jobs never fail the uninstall;
@PreserveRunLogsemantics are unchanged. -
Install on platforms without SQL Agent (
@Mode = Install,
@CreateAgentJob = 1on Azure SQL Database / Express): no job is attempted;
the Install result now states that BOTH
EXEC dbo.sp_SQLFlightRecorder @Mode = N'Collect';and
EXEC dbo.sp_SQLFlightRecorder @Mode = N'Purge', @WhatIf = 0;must be
scheduled externally. -
Report window-first reads (
@Mode = Report; performance only, output
contract and rule behavior unchanged): the baseline builder, restart
detection, FR_R0005's corroborating counter read, FR_R0021–FR_R0024's
window scans, and the v0.4 timeline events now carry child-side
SnapshotUtcrange predicates (the child value always equals its parent's),
so every read rides the clustered index instead of joining through the
parent alone. The schema-activity timeline is rewritten window-first with
boundedSnapshotUtcaccess, deduplicated per distinct event (the collector
re-captures each event on every snapshot in its 7-day lookback; the timeline
previously emitted those duplicates), and capped at@MaxFindingswith the
Coverage warning above. -
Repository footprint row counts (
@Mode = Statusresult set 5 and
FR_v_RepositoryFootprint):RowCountnow counts heap/clustered rows only
(index_id IN (0, 1)), so the new nonclustered indexes do not inflate it;
UsedKbstill includes index pages. -
CriticalWaitTypeshonoring is not part of this release (RuleId
FR_R0003_TopWaitTypeSpike): D-105 originally targeted "v1.1"; 1.1.0 ships
retention hardening only, so FR_R0003 still uses the hard-coded D-093 list
and the honoring moves to a later 1.x minor (D-200). The config key
remains defined and settable, exactly as in v1.0.0. -
Upgrade harness (
tests/upgrade/run-upgrade.sh) now asserts that
SchemaVersionadvances to the current artifact's value (measured from a
fresh reference install, not a hard-coded string) and that the new
SnapshotIdindexes exist after upgrade. -
Purge is documented as mandatory operational maintenance across README,
the user guide,docs/configuration.md(retention ranges and the
not-a-warehouse note),docs/operations/scheduling.md(per-platform purge
scheduling, including Azure SQL Database external scheduling of both
statements),docs/operations/troubleshooting.md(huge-repository /
slow-Report recovery), and the regenerated mode pages for Install,
Uninstall, Status, Configure, and Purge. -
Azure SQL Managed Instance and Azure SQL Database are certified as
supported (D-196), both Verified by manual Tier-2 attestation against
v1.0.0. MI ran the full collector set with onlyAlwaysOnStateskipped;
Azure SQL Database returnedSuccesswith four collectors skipped by design —
AgentJobs,BackupHistory,Deadlocks,AlwaysOnState— each reason
carried in theFR_R0026coverage finding. Both installed 25 coreFR_*
tables plus 5FR_v_*views and uninstalled leavingRemainingFrObjects = 0.
No equivalence is claimed between the two, or between either and on-prem. -
The compatibility matrix now lists every version and platform explicitly —
no collapsed "2017+" row — including separate rows for SQL Server on Azure VM
(IaaS), which is the ordinary engine on a VM you administer and inherits its
matching on-prem row, as distinct from the Azure PaaS products. -
The matrix states plainly that Tier-2 "Verified" is not Tier-1 verified: it
is one manual run at one point in time, where Tier 1 is an automated per-push
gate that blocks the build on failure. -
Primary supported range is now SQL Server 2014–2025 (D-195, amending
D-108's range framing). SQL Server 2012 is demoted to legacy best-effort:
thev1.0.0lifecycle was manually tested on 2012 Windows and completed, but
with a knownSchemaActivitycollector degradation — bothCollectruns
returnedPartialSuccess(dbsDone=0; dbErrors=1; budgetHit=0). Platform
split now stated wherever compatibility is claimed: 2017+ on Linux and
Windows, 2014/2016 Windows-only, 2012 Windows-only best-effort. -
SQL Server 2014 and 2016 (Windows) are now Tier-2 Verified on manual
v1.0.0attestations — full lifecycle Success, evidence and caveats recorded
in the compatibility matrix. This is the first upgrade of a Tier-2 status on
real evidence, which is the only path D-192 permits. -
Note for anyone comparing docs with the tool: the released
1.0.0artifact
reportsSupportedSqlServerRange = 'SQL Server 2012–2025'. That is not false
— 2012 remains supported best-effort — but it is coarser than this policy, and
the artifact is immutable.
sp_SQLFlightRecorder 1.0.0
[1.0.0] - 2026-07-29
First stable release. The v1.x contract starts here: rule IDs, output
columns, and the forward-only schema are now "1.0 is forever" promises — see
docs/compatibility/support-policy.md.
Relative to 1.0.0-rc.1 the only artifact change is version metadata:
ToolVersion 1.0.0-rc.1 → 1.0.0 and the build date. Everything else in this
entry is documentation and process. SchemaVersion stays 0.4.0 (no DDL,
forward-only, D-038) and RulePackVersion stays 0.4.3 — it names the release
that last changed rule logic or the rule catalog, not the tool release (D-085),
and no rule has changed since 0.4.3.
Compatibility, stated by tier. Tier-1 verified in automated CI: SQL
Server 2017 / 2019 / 2022 / 2025 Developer, plus 2022 Express and Standard.
Tier-2 Unverified — no attestation received, meaning untested, not "works"
and not "broken": SQL Server 2012 / 2014 / 2016 (Windows), Azure SQL Managed
Instance, Azure SQL Database. The two tiers are separate claims; see
docs/compatibility/matrix.md before relying on a
Tier-2 target.
Upgrades from 0.4.1 / 0.4.2 / 0.4.3 / 1.0.0-rc.1 are validated and
migration-free (tests/upgrade/run-upgrade.sh). v0.4.0 has no public tag and
is untested — not faked, not claimed.
Changed
ToolVersionis now1.0.0(surfaced byAbout,Help,Status, and the
Markdown report header; build date 2026-07-29). No behavior change.- Security reporting now has a dedicated private contact.
SECURITY.md
directs vulnerability reports to
sqlflightrecorder-security@forwardthinkersconsulting.com. GitHub private
vulnerability reporting is not enabled on this repository, and the policy
says so rather than pointing reporters at a Report a vulnerability button
that is not available to them. - Conduct reporting has a designated v1.0.0 path.
CODE_OF_CONDUCT.md
routes reports to the repository owner through GitHub maintainer channels,
with a fallback for reporters who have no private channel, marked explicitly
as the v1.0.0 path rather than a placeholder. No address invented. It also
states that a single-maintainer project cannot independently review a report
about that maintainer, and points to GitHub's own abuse reporting as an
independent route. - Owner sign-off is sufficient for the v1.0.0 wording lock (D-193),
superseding D-158's two-reviewer rule and D-189's second-reviewer eligibility
for that sign-off only. Two-maintainer review resumes automatically once a
second maintainer exists or the project moves to an organization/team model.
This narrows who signs off, not what §6.7 requires of the wording. - Cost-regression (D-143) and soak (D-145) are not a v1.0.0 gate
(D-194). No green evidence exists for either and none is claimed: both
workflows are schedule/dispatch-only by design, and scheduled workflows run
only from the default branch, where neither file exists yet. - Tier-2 attestation is no longer a v1.0.0 release gate (D-192). The
earlier §11.6 rule required at least 4 of 5 Tier-2 targets attested before
final v1.0.0; final v1.0.0 may now ship with those targets Unverified.
What replaces the count is a wording obligation: compatibility claims must
keep Tier-1 verified (automated CI evidence) and Tier-2 pending /
unverified (no attestation received) visibly separate, and no unattested
target may be described as verified or tested. SQL Server 2012, 2014 and 2016
and the Azure targets stay Unverified — untested, not "works", not "broken"
— until a real attestation is recorded. Attestation collection continues as
post-1.0 work under D-164 and the D-190 18-month review. - The Tier-2 attestation issue template now requires the capability snapshot
and takes it as a multi-line field. The process always listed it as required
evidence — it is what pins which target the evidence describes — but the
template marked it optional, so an attestation could arrive unrecordable. - The upgrade harness now includes
1.0.0-rc.1as a source version, so the
RC-to-final upgrade path is covered. Fixed a latent bug it exposed: database
names were built by stripping dots only, so a prerelease version's hyphen
produced an illegal identifier. - The hotfix process (D-174) was rehearsed before this release: branch from
the latest tag, minimal fix, validation, forward-merge. Recorded with its
limits indocs/release-readiness-v1.0.0-rc.1.md— the rehearsal used a
docs-only fix, so it did not exercise the regression-test leg.
sp_SQLFlightRecorder 1.0.0-rc.1
[1.0.0-rc.1] - 2026-07-21
First release candidate for v1.0.0. This is a documentation, CI/release-process,
and version-metadata stabilization on top of 0.4.3. It changes no schema,
output contract, rule ID, rule logic, collector, or mode: SchemaVersion stays
0.4.0, and RulePackVersion stays 0.4.3 because no rule logic or catalog
entry changed since 0.4.3 (the rule-pack version names the last rule change, not
the tool release — D-085). Upgrades from 0.4.1 / 0.4.2 / 0.4.3 are validated and
migration-free.
Changed
ToolVersionis now1.0.0-rc.1(surfaced byAbout,Help,Status, and
the Markdown report header; build date 2026-07-21). No behavior change.
Added
- Documentation completeness (§11.6): a page for every mode, rule, and
config key, enforced by a CI doc-coverage gate (scripts/check-doc-coverage.sh)
plus rule/mode/compat-matrix generators. - CI / release wiring: rule fixtures + demo golden in CI; a dry-runnable
release workflow (release.yml) that builds a byte-identical artifact with a
checksum and attaches the compatibility matrix; out-of-band cost/soak harnesses
(non-blocking). - Compatibility: six Tier-1 verified targets (2017/2019/2022/2025 Developer +
2022 Express/Standard) and a documented Tier-2 attestation process for
2012/2014/2016 Windows + Azure MI/DB (pending attestation). - Upgrade-path validation harness (
tests/upgrade/run-upgrade.sh). - Security / support / governance docs: threat-model, support policy,
contributing guides, CODEOWNERS, and eight issue templates.
Notes
- The D-076 / D-189 wording lock was reviewed with no changes required: every
rule recommendation is advisory and evidence-gated ("consider … only after
validating"), with explicit guards against reflexive action; no unsafe advice
is present (no kill / force /NOLOCK/ shrink; no unqualified root-cause
claims). Seedocs/wording-lock-review.md. - Must resolve before final v1.0.0: a dedicated private security contact or
GitHub private vulnerability reporting; a dedicated conduct contact; the
two-maintainer wording sign-off; ≥ 4 of 5 Tier-2 attestations; and,
optionally, the historicalv0.4.0upgrade artifact (no publicv0.4.0tag
exists).SECURITY.mdandCODE_OF_CONDUCT.mddescribe the channels that
exist today rather than promising contacts that do not — no placeholder
addresses are published. - CODEOWNERS routes to the repository owner account
@forward-thinkers-lab.
The repository is owned by a user account, not an organization, so GitHub team
syntax cannot resolve here; D-185's@core-maintainersteam routing is
superseded by D-191 and reactivated only if the project moves under an
organization.