Skip to summary
Sample report — fictional company and dataSaguaro Medical Billing LLC is not a real client. Every server name, account, number and finding below is invented to show the format of a GracePath Ventures review.
Database & Technology Services · Sample deliverable

Database Health, Access & Modernization Review

Prepared for Saguaro Medical Billing LLC (Sample) — SQL Server, PostgreSQL and Oracle: recovery readiness, user access, security, performance, capacity and version support.

Data collectedOctober 13, 2026
MethodRead-only scripts + owner interview
Scope4 servers · 3 platforms · 10 databases
CoversLevel 1 Health & Access Check + Level 2 Modernization Plan
Prepared byElvis Akumbom, GracePath Ventures
StatusSample · v1.0

1Executive summary

Your databases are working day to day, but the business is exposed in four ways: the billing server runs SQL Server 2016, which Microsoft stopped supporting on July 14, 2026; the document-intake database (PostgreSQL 14) loses support on November 12 and its backups are failing; too many people and programs have full administrator access on every platform; and no backup has ever been proven to restore. None of this needs a big-bang project. The first two to five weeks remove most of the risk, and the upgrades can then be planned calmly.

3Critical findings
9High findings
19full-admin accounts, excluding service accounts (about 6 needed)
0restore tests on record (12 months)

What this means in plain terms

  • If the billing server failed tonight, you could lose up to a day of billing work, and nobody knows how long the restore would take. Your stated target is one hour of data and four hours of downtime.
  • The document-intake backups have failed for three nights because its disk is nearly full. Four days of scanned documents are unprotected.
  • Access is too open: application, vendor and former-staff accounts have full admin rights, several people share logins, and built-in master accounts are in use.
  • Patient and billing data is not encrypted on disk, in backups or on the network.
  • The good news: the portal server (SQL Server 2019) and the ledger (Oracle 19c) are on supported versions. They need patching, access clean-up and better backups — not replacement.

Top five actions

  1. This week: free the PostgreSQL disk, get a good intake backup, and copy all backups off the servers.
  2. Within two weeks: timed test restores of the billing, intake and ledger databases.
  3. Within two weeks: add the missing SQL Server log backups before the log drive fills.
  4. Within five weeks: user access clean-up — named admins only, no shared or default accounts, unused accounts removed.
  5. Next quarter: move the billing server to SQL Server 2022/2025 on a supported Windows Server (ESU only as a bridge) and the intake database to PostgreSQL 17/18.

Scorecard by server

ServerSupported versionBackupsRestore provenUser accessEncryptionPerformanceCapacity
SMB-SQL01 · SQL Server 2016 Ended (Critical) Partial (High) No (Critical) Weak (High) None (High) Defaults (Medium) ~10 months (Medium)
SMB-SQL02 · SQL Server 2019 Yes (2030) (Healthy) Local only (High) No (Critical) Fair (High) Not enabled (High) Good (Healthy) OK (Healthy)
SMB-PG01 · PostgreSQL 14 Ends Nov 12 (High) Failing (Critical) No (Critical) Weak (High) No SSL (High) Vacuum lag (Low) 91% full (High)
SMB-ORA01 · Oracle 19c Yes, RU behind (Medium) Same storage (High) No (Critical) Weak (High) Backups clear (Medium) OK (Healthy) OK (Healthy)
▲ Critical▲ High■ Medium◆ Low● Healthy

2Scope and method

What was reviewed

Level 1 — Health & Access Check

  • Backups, restore history and recovery targets (RPO/RTO).
  • User access review: who has admin, shared accounts, orphaned and unused accounts, default accounts, password rules, least privilege.
  • Security settings and encryption.
  • Performance basics, maintenance jobs and capacity.

Level 2 — Modernization Plan

  • Version and patch support status on each platform.
  • Upgrade and migration paths, including cross-platform and Azure options.
  • Phased roadmap.

How

Read-only script packs for SQL Server (T-SQL), PostgreSQL and Oracle — SELECT statements against system views only; nothing is changed and no operating-system commands are run — executed with temporary read-only accounts, plus a one-hour interview with the owner and IT contact. Disk free space on the Linux server was supplied by IT.

Not in scope

Application code review, network and firewall configuration, operating-system patching, licensing audits, round-the-clock monitoring, and any change to the servers. Licensing and pricing questions go to Microsoft, Oracle or your licensing partner. Nothing in this report is legal, compliance or tax advice.

3Server register

ServerPlatform · versionEditionHostRoleSizeSupport
SMB-SQL01SQL Server 2016 SP2
13.0.5026.0
StandardWindows Server 2016 VM · 8 vCPU · 32 GBProduction billing, EDI claims, SSRS reports5 user DBs · ~631 GBCritical Ended Jul 14, 2026
SMB-SQL02SQL Server 2019 CU18
15.0.4261.1
StandardWindows Server 2019 VM · 4 vCPU · 16 GBPatient payment portal, integrations (SSIS)3 user DBs · ~51 GB Supported to Jan 9, 2030
SMB-PG01PostgreSQL 14.9
server_version_num 140009
CommunityLinux VM · 4 vCPU · 16 GBDocument intake & scanning app1 app DB · 64 GBHigh Fixes end Nov 12, 2026
SMB-ORA01Oracle Database 19c
RU 19.18.0.0.230117
Standard Edition 2Oracle Linux VM · 8 vCPU · 64 GBGeneral ledger & payroll (vendor package)1 PDB · 212 GBMedium 19c supported; RU behind

Support dates: SQL Server 2016 extended support ended July 14, 2026[1][2]; SQL Server 2019 runs to January 9, 2030[4]; SQL Server 2022 to January 11, 2033[5]; SQL Server 2025 to January 6, 2036[6] (Microsoft lists each end as early morning UTC of the following day). PostgreSQL 14 stops receiving fixes on November 12, 2026[13]. Oracle 19c Premier Support has been announced to December 31, 2029[15].

Databases

ServerDatabaseData GBLog / WAL GBRecovery modeLevelLast full / dumpLast log / archiveNote
SMB-SQL01BillingCore182.424.0FULLcompat 130Oct 13 01:12Oct 13 14:30Log backup every 30 min
SMB-SQL01ClaimsArchive418.26.1SIMPLEcompat 110Oct 11 02:40—Weekly full only
SMB-SQL01EDI_Staging26.371.4FULLcompat 130Oct 13 01:55Neverlog_reuse_wait LOG_BACKUP
SMB-SQL01ReportServer3.12.2FULLcompat 130Oct 13 01:58Neverlog_reuse_wait LOG_BACKUP
SMB-SQL01ReportServerTempDB0.80.3SIMPLEcompat 130Oct 13 01:59—
SMB-SQL02PracticePortal38.24.0FULLcompat 150Oct 13 00:41Oct 13 14:45Log backup every 15 min
SMB-SQL02Integration8.91.1SIMPLEcompat 140Oct 13 00:52—
SMB-SQL02SSISDB4.00.6SIMPLEcompat 150Oct 13 00:55—
SMB-PG01docintake64.241.6archive_mode offPG 14Oct 9 23:30 (pg_dump)No WAL archivingDumps failing since Oct 10
SMB-ORA01LEDGERPDB212.0—ARCHIVELOG19c SE2Oct 13 01:00 (RMAN L1)Oct 13 14:00L0 weekly · archivelogs every 2 h

Times are server local time on the collection date. SQL Server compat 130 = 2016 level, 150 = 2019, 140 = 2017, 110 = 2012.

4Recovery targets vs. reality

RPO is how much recent work you can afford to lose; RTO is how long you can be down. The targets are the ones the owner gave in the interview.

DatabaseTarget RPO / RTOActual RPO todayRTO evidenceResult
BillingCore (SQL Server)1 hour / 4 hours30 min on-server; up to ~24 h if the VM or its storage is lost (NAS copy nightly at 03:00)Unproven — never restoredNot met
EDI_Staging (SQL Server)24 hours / 1 dayNightly full; re-loadable from source EDI files (per interview)UnprovenAt risk (log drive)
PracticePortal (SQL Server)1 hour / 8 hours15 min on-server; no off-host copyUnprovenNot met
docintake (PostgreSQL)4 hours / 1 day4 days (last good dump Oct 9); no point-in-time recoveryUnprovenNot met
LEDGERPDB (Oracle)2 hours / 8 hours2 h on-server; backups on the same SAN as the dataUnproven — no RESTORE VALIDATE in 12 monthsPartly met

5User access review

Who can get into each database, with how much power, and whether every account still belongs to a real, current person or system. Least privilege means each person and application has only the access its job needs. Details and evidence are in findings F-05 to F-07.

ServerFull-admin accountsShared accountsOrphaned / unusedDefault / built-inPassword rulesLeast privilege?
SMB-SQL017 sysadmin besides service accounts (3 app logins, 1 former contractor) · suggest 2sa used by EDI script from SMB-EDI017 orphaned users in BillingCore; SMB\jmoralessa enabled, password from 20194 SQL logins without policyNot least privilege
SMB-SQL022 sysadmin besides service accounts (incl. portal_app) · suggest 1None seen in review window0 orphanedsa disabledportal_app without policyPartly
SMB-PG014 superusers (incl. app and replicator) · suggest 1postgres from 3 workstationsCannot tell — connection logging offpostgres in daily usemd5 on 9 of 11 roles; no expiryNot least privilege
SMB-ORA016 with DBA role (incl. app and vendor) · suggest 2LEDGER_ADMIN: 7 machines, 6 OS users11 open, unused 90+ days (3 former staff)DBSNMP open with default passwordUnlimited lifetime and failed loginsNot least privilege

Whether a person has left the business was confirmed with the owner, not read from the database. PostgreSQL and SQL Server do not store last-login dates by default; Oracle does (DBA_USERS.LAST_LOGIN).

6Findings

22 findings: 3 critical, 9 high, 8 medium, 2 low. Each shows the evidence from the read-only scripts (fictional output), why it matters, and what to do.

IDSeverityAreaFindingServer(s)
F-01CriticalSupportabilityThe billing server runs SQL Server 2016, which reached end of support on July 14, 2026SMB-SQL01
F-02CriticalBackup & recoveryThe document-intake database has no point-in-time recovery, and its nightly dump has failed for three nightsSMB-PG01
F-03CriticalBackup & recoveryNo restore has ever been tested, and backups sit on the same server or storage as the dataAll four
F-04HighBackup & recoverySQL Server log backups are missing for two FULL-recovery databases; the log drive is 93% fullSMB-SQL01
F-05HighUser accessToo many accounts have full administrator rights — on every platformSMB-SQL01, SMB-SQL02, SMB-PG01, SMB-ORA01
F-06HighUser accessShared and built-in accounts are in daily useSMB-SQL01, SMB-PG01, SMB-ORA01
F-07HighUser accessOrphaned and unused accounts remain, and password rules are weakSMB-SQL01, SMB-PG01, SMB-ORA01
F-08HighSecurityBilling and patient data is not encrypted at rest, in backups, or on the networkSMB-SQL01, SMB-SQL02, SMB-PG01, SMB-ORA01
F-09HighOperationsSQL Server integrity checks have been off for 11 months, and index maintenance fails every weekSMB-SQL01
F-10HighSupportabilityPostgreSQL 14 stops receiving fixes on November 12, 2026, and this server is 15 updates behindSMB-PG01
F-11HighCapacityA forgotten replication slot is holding 38 GB of logs and filling the PostgreSQL volumeSMB-PG01
F-12HighSupportabilityThe billing server’s Windows version reaches end of support on January 12, 2027SMB-SQL01
F-13MediumPerformanceMemory, parallelism and tempdb are at default settings on the billing serverSMB-SQL01
F-14MediumPerformanceIndex health: heavy fragmentation, unused indexes and one very large heapSMB-SQL01
F-15MediumCapacitySQL Server data drive has about 10 months of room; autogrowth settings are poorSMB-SQL01
F-16MediumSupportabilitySupported servers are behind on updatesSMB-SQL02, SMB-ORA01
F-17MediumSecurityxp_cmdshell is enabled on the billing server and used by three EDI proceduresSMB-SQL01
F-18MediumOperationsNobody is notified when a job or backup failsAll four
F-19MediumModernization readinessItems to resolve before moving the billing serverSMB-SQL01
F-20MediumHigh availabilityNo standby for the billing or ledger databasesSMB-SQL01, SMB-ORA01
F-21LowPerformancePostgreSQL vacuum is falling behind on the main documents tableSMB-PG01
F-22LowModernization readinessDeprecated SQL Server features are in use (warnings, not blockers)SMB-SQL01
F-01CriticalSupportability

The billing server runs SQL Server 2016, which reached end of support on July 14, 2026

Server(s): SMB-SQL01

Your main billing database server no longer receives regular security fixes from Microsoft, and it is not even on the last service pack.

Evidence (sample script output)
SMB-SQL01  product_version 13.0.5026.0  product_level SP2  update_level NULL
           edition Standard Edition (64-bit)  engine_edition 2
Why it matters

Microsoft ended extended support for SQL Server 2016 on July 14, 2026[1][2]. Paid Extended Security Updates (ESU) deliver critical security updates for up to three years (Year 3 ends July 17, 2029)[2] and are bought per server through the Azure portal, with on-premises servers connected through Azure Arc[3]. Standard edition is eligible[3]. Service Pack 3 is the final service pack for SQL Server 2016[2].

Recommendation

Plan a move off SQL Server 2016 (see the recommended path). Bring SMB-SQL01 to SP3 and its final update as a first step. Decide by an agreed date whether ESU is needed as a short bridge; get current ESU pricing directly from Microsoft or your licensing partner — this report does not quote it.

Source: sqlserver/01_instance_inventory.sql
F-02CriticalBackup & recovery

The document-intake database has no point-in-time recovery, and its nightly dump has failed for three nights

Server(s): SMB-PG01

If the intake server failed today, you would lose everything scanned since Thursday night — four days of documents — and nobody has been told the backup is failing.

Evidence (sample script output)
archive_mode off · wal_level replica · pg_stat_archiver.archived_count 0
docintake  size 64 GB
Last successful pg_dump: 2026-10-09 23:30  (cron log on server; Oct 10–12 runs exited with
  "No space left on device" — dump target /backup is on the same 500 GB volume as the data)
Why it matters

Without WAL archiving, PostgreSQL can only be restored to the moment of the last dump, so the recovery point is at best one day. The dumps are now failing because the shared volume is almost full (see F-11), and the failure is only visible in a log file nobody reads.

Recommendation

Free space safely (F-11), confirm a good dump today and copy it off the server. Then set up WAL archiving with a proper PostgreSQL backup tool to separate storage so you can restore to any point in time, and alert your IT contact when a backup fails.

Source: postgresql/01_inventory_settings.sql · postgresql/02_databases_backup_wal.sql
F-03CriticalBackup & recovery

No restore has ever been tested, and backups sit on the same server or storage as the data

Server(s): All four

There is no evidence that any backup on any platform can actually be restored, or how long it would take. Most backup files live on the same machine or storage array as the databases they protect.

Evidence (sample script output)
SQL Server  restorehistory (12 months): 0 rows on SMB-SQL01 and SMB-SQL02
SMB-SQL01   sample_destination E:\SQLBackups\BillingCore\BillingCore_FULL_20261013_010001.bak
SMB-SQL02   sample_destination D:\Backup\PracticePortal\PracticePortal_LOG_20261013_144500.trn
SMB-ORA01   v$rman_status RESTORE/VALIDATE (12 months): 0 rows
            backup pieces: DISK · Local/NFS path /u03/fra/LEDGER/...  (same SAN as data, per interview)
SMB-PG01    pg_dump files in /backup on the data volume
SQL Server backups: encryption_algorithm NULL · all_have_checksums 0
Why it matters

Your stated targets are a 1-hour recovery point (RPO) and a 4-hour recovery time (RTO) for billing. On SMB-SQL01 a nightly copy to the NAS runs at 03:00 (per interview), so losing the VM or its storage could lose up to about a day of billing work, not one hour. With no timed restore on any platform, every RTO is unproven.

Recommendation

Copy backups off-host as they are taken (not once a night), keep at least one copy that ransomware on the server cannot reach, turn on SQL Server backup checksums, and run a timed restore of BillingCore, docintake and LEDGERPDB to a test server now and quarterly after that.

Source: sqlserver/03_backup_history.sql · oracle/02_backup_recovery.sql · postgresql/02_databases_backup_wal.sql
F-04HighBackup & recovery

SQL Server log backups are missing for two FULL-recovery databases; the log drive is 93% full

Server(s): SMB-SQL01

Two databases keep a full history of changes that is never backed up, so it keeps growing. When the log drive fills, those databases stop accepting work — including EDI claim imports.

Evidence (sample script output)
EDI_Staging   recovery FULL  last_log NULL  log_gb 71.4  log_reuse_wait_desc LOG_BACKUP
ReportServer  recovery FULL  last_log NULL  log_gb 2.2   log_reuse_wait_desc LOG_BACKUP
L:\  total_gb 120.0  free_gb 8.4  free_pct 7.0
Why it matters

In FULL recovery, log space is only reused after a log backup. Without one, the log grows until the disk is full and the database refuses writes.

Recommendation

Decide the needed recovery point for each database. For EDI_Staging (re-loadable staging data) SIMPLE recovery may be appropriate; for ReportServer add log backups. Then reclaim log space once, in a maintenance window, and size the log properly.

Source: sqlserver/02_databases.sql · sqlserver/03_backup_history.sql · sqlserver/09_disk_file_growth.sql
F-05HighUser access

Too many accounts have full administrator rights — on every platform

Server(s): SMB-SQL01, SMB-SQL02, SMB-PG01, SMB-ORA01

Application accounts, a vendor support account and a former contractor can all do anything on the database servers. Only a handful of named people should.

Evidence (sample script output)
SMB-SQL01 sysadmin (9): sa · NT SERVICE\MSSQLSERVER · NT SERVICE\SQLSERVERAGENT · SMB\Domain Admins ·
  SMB\IT-Support (group) · SMB\jmorales (enabled) · billing_app · edi_import · svc_ssrs
SMB-SQL02 sysadmin (4): NT SERVICE\MSSQLSERVER · NT SERVICE\SQLSERVERAGENT · SMB\DBA-Admins · portal_app
SMB-PG01  rolsuper = true (4): postgres · docintake_app · kbrown · replicator
SMB-ORA01 granted_role DBA (6): LEDGER_ADMIN · LEDGER_APP · LEDGER_VENDOR · BACKUP_USER · DPATEL · MLOPEZ
Why it matters

If any application is compromised — for example through the internet-facing payment portal — administrator rights let an attacker read every database, create new accounts and, on SMB-SQL01 where xp_cmdshell is on, run commands on the server. The PostgreSQL replicator role only needs the REPLICATION attribute, not superuser.

Recommendation

Agree a short list of named administrators per platform. Replace admin rights on application accounts with only the rights each app needs (database roles / object grants). Give the vendor account a time-limited, logged access route. Remove SMB\jmorales after confirming with HR that the contract ended.

Source: sqlserver/05_security_logins.sql · postgresql/03_roles_access_review.sql · oracle/03_users_access_review.sql
F-06HighUser access

Shared and built-in accounts are in daily use

Server(s): SMB-SQL01, SMB-PG01, SMB-ORA01

Several people log in with the same account, so nobody can tell who did what. Built-in master accounts are switched on and in use.

Evidence (sample script output)
SMB-SQL01  sa_is_disabled 0  sa_policy_checked 0  sa_password_last_set 2019-03-04  (Mixed mode)
           sessions: login_name sa  program_name SQLCMD  host_name SMB-EDI01
SMB-PG01   usename postgres  distinct_client_addresses 3  (three staff workstations, per interview)
SMB-ORA01  LEDGER_ADMIN  distinct_machines 7  distinct_os_users 6  sessions 11
           dba_users_with_defpwd: DBSNMP  account_status OPEN
Why it matters

Shared accounts make audits and investigations impossible and mean a password can never really be changed. The sa and postgres accounts are the first ones attackers try; an Oracle account still using a published default password is effectively unlocked.

Recommendation

Give each person their own named account and each application its own login. Lock DBSNMP (or change its password if a monitoring tool needs it). Change the EDI script to its own login, then disable sa. Keep the postgres role for local maintenance only.

Source: sqlserver/05_security_logins.sql · sqlserver/12_user_access_review.sql · postgresql/03_roles_access_review.sql · oracle/03_users_access_review.sql
F-07HighUser access

Orphaned and unused accounts remain, and password rules are weak

Server(s): SMB-SQL01, SMB-PG01, SMB-ORA01

Accounts for people and systems that are no longer around are still open, and several platforms let passwords live forever.

Evidence (sample script output)
SMB-SQL01  BillingCore orphaned users (no matching login): 7
           SQL logins with is_policy_checked = 0: 4 (sa, billing_app, edi_import, svc_ssrs)
SMB-ORA01  OPEN accounts with last_login > 90 days or never: 11 (incl. 3 named for former staff)
           profile DEFAULT  PASSWORD_LIFE_TIME UNLIMITED · LEDGER_APP_PROFILE FAILED_LOGIN_ATTEMPTS UNLIMITED
SMB-PG01   password_method md5 (legacy): 9 of 11 login roles · rolvaliduntil NULL on all
           log_connections off → unused roles cannot be identified from the database
Why it matters

Every open account is a door. Old accounts are rarely watched, so they are a favorite way in. PostgreSQL does not record last-login dates, so connection logging has to be turned on before unused roles can be found.

Recommendation

Confirm each account with its owner (HR for people, IT for systems), then lock, monitor for complaints for two weeks, and drop. Apply sensible password and lockout rules. In PostgreSQL move to SCRAM-SHA-256 and turn on connection logging.

Source: sqlserver/12_user_access_review.sql · oracle/03_users_access_review.sql · postgresql/01_inventory_settings.sql · postgresql/03_roles_access_review.sql
F-08HighSecurity

Billing and patient data is not encrypted at rest, in backups, or on the network

Server(s): SMB-SQL01, SMB-SQL02, SMB-PG01, SMB-ORA01

If a database or backup file were copied off a server, it could be read as-is. Connections from the applications are not encrypted either.

Evidence (sample script output)
SQL Server  sys.dm_database_encryption_keys: 0 rows (both servers)
            dm_exec_connections encrypt_option FALSE: 214 (SMB-SQL01) · 96 (SMB-SQL02)
PostgreSQL  ssl off · pg_stat_ssl.ssl false for all 38 client sessions
Oracle      v$rman_configuration: no ENCRYPTION setting (backups unencrypted on disk)
Why it matters

On SQL Server 2016, Transparent Data Encryption (TDE) is an Enterprise-edition feature, so SMB-SQL01 (Standard) cannot use it today; Standard edition gained TDE in SQL Server 2019[12], so SMB-SQL02 could enable it now. Oracle encryption options depend on edition and license — confirm with Oracle before planning. Because these systems hold health and billing information, review the encryption decisions with your compliance advisor — this report is not legal or compliance advice.

Recommendation

Enable TDE on PracticePortal with the certificate backed up separately; turn on SQL Server backup encryption; enable SSL in PostgreSQL and require it in pg_hba for network connections; install trusted certificates and force encrypted SQL Server connections after testing each app. Include encryption in the SMB-SQL01 target design.

Source: sqlserver/02_databases.sql · sqlserver/05_security_logins.sql · postgresql/03_roles_access_review.sql · oracle/02_backup_recovery.sql
F-09HighOperations

SQL Server integrity checks have been off for 11 months, and index maintenance fails every week

Server(s): SMB-SQL01

Nobody would know if the billing database had quiet corruption, and the weekly tune-up job has failed every run since August.

Evidence (sample script output)
job_name                      enabled  failures_30d  successes_30d  last_run
Maint - Weekly Index Rebuild    1          4             0          2026-10-11 02:00
DBA - CHECKDB Weekly            0          0             0          2025-11-09 03:00
EDI - Import 837 Files          1          2            28          2026-10-13 06:15
last failure (Index Rebuild, step 1): Msg 1712 — Online index operations can only be
  performed in Enterprise edition of SQL Server.
Why it matters

Corruption found late is often unrecoverable because the backups contain it too. The index job was changed in August to use ONLINE = ON, which Standard edition does not support, so it fails immediately and does nothing — which is why fragmentation has built up (F-14).

Recommendation

Re-enable a weekly DBCC CHECKDB (against a restored copy if the window is tight). Fix the index job for Standard edition and rebuild only what needs it.

Source: sqlserver/04_agent_job_failures.sql
F-10HighSupportability

PostgreSQL 14 stops receiving fixes on November 12, 2026, and this server is 15 updates behind

Server(s): SMB-PG01

The intake database’s version is about to lose all security and bug fixes from the PostgreSQL project, and it has not had the fixes released in the last three years either.

Evidence (sample script output)
server_version 14.9 · server_version_num 140009 · uptime 211 days
Why it matters

The PostgreSQL project states that PostgreSQL 14 stops receiving fixes on November 12, 2026; the final 14.x minor release listed is 14.24[13]. Supported major versions include 17 (to November 2029) and 18 (to November 2030)[14].

Recommendation

Short term: apply 14.24 (a minor update — no data conversion) in the next window. Then upgrade to PostgreSQL 17 or 18 after confirming the intake application supports it; rehearse with pg_upgrade on a copy first.

Source: postgresql/01_inventory_settings.sql
F-11HighCapacity

A forgotten replication slot is holding 38 GB of logs and filling the PostgreSQL volume

Server(s): SMB-PG01

An old, disconnected copy of the database is still being ‘waited for’, so PostgreSQL keeps every change log for it. The disk is 91% full, which is what broke the nightly backups.

Evidence (sample script output)
slot_name old_replica_dr  slot_type physical  active false  wal_status extended  retained_wal 38 GB
pg_ls_waldir: 2,661 files · 41.6 GB
/var/lib/postgresql (df -h, from IT): 500 GB · 91% used
Why it matters

A replication slot tells PostgreSQL to keep logs until a replica has received them. The DR replica it belonged to was switched off in the spring (per interview), so the logs will grow until the disk is full and PostgreSQL stops.

Recommendation

Confirm the old replica is truly retired, then drop the slot in a change window and watch the WAL directory shrink. Move backups to separate storage. Re-introduce a standby later only with monitoring of its slot by your IT team.

Source: postgresql/02_databases_backup_wal.sql · postgresql/06_capacity.sql
F-12HighSupportability

The billing server’s Windows version reaches end of support on January 12, 2027

Server(s): SMB-SQL01

Even after a SQL Server fix, the operating system underneath loses support in three months.

Evidence (sample script output)
SMB-SQL01  windows_release 10.0  (Windows Server 2016 Standard, per inventory)
Why it matters

Windows Server 2016 extended support ends January 12, 2027[10]. An in-place SQL Server upgrade on this host would leave the operating-system problem unsolved.

Recommendation

Use a side-by-side migration to a new server on a currently supported Windows Server rather than an in-place upgrade.

Source: sqlserver/01_instance_inventory.sql
F-13MediumPerformance

Memory, parallelism and tempdb are at default settings on the billing server

Server(s): SMB-SQL01

The billing server is set up the way it came out of the box, which makes it slower than it needs to be and can starve Windows of memory.

Evidence (sample script output)
max server memory (MB)         2147483647   (physical_memory_mb 32,767 → Not capped)
max degree of parallelism       0
cost threshold for parallelism  5
Page life expectancy            212 s
tempdb: 1 data file (24,576 MB, growth 10 %)
Top waits (38 days): CXPACKET 34.1 % · PAGEIOLATCH_SH 22.7 % · WRITELOG 9.8 % · LCK_M_U 6.2 % ·
  SOS_SCHEDULER_YIELD 5.9 % · ASYNC_NETWORK_IO 4.4 % · PAGELATCH_UP 3.1 %
Why it matters

High CXPACKET with MAXDOP 0 and a cost threshold of 5 points to small queries going parallel unnecessarily. PAGEIOLATCH waits and a low page life expectancy show data being re-read from disk. PAGELATCH_UP on a single tempdb file suggests allocation contention. SMB-SQL02, by contrast, is configured sensibly.

Recommendation

Cap max server memory (around 27–28 GB to start), set MAXDOP to 4–8 and cost threshold to 50 as a starting point, add equal-size tempdb data files. Change one thing at a time and compare waits before and after.

Source: sqlserver/06_configuration.sql · sqlserver/07_wait_stats.sql
F-14MediumPerformance

Index health: heavy fragmentation, unused indexes and one very large heap

Server(s): SMB-SQL01

Several of the busiest billing tables are stored inefficiently, and the optimizer keeps asking for an index that does not exist.

Evidence (sample script output)
BillingCore: 41 indexes ≥ 30 % fragmented and ≥ 1,000 pages
  dbo.ClaimLine  IX_ClaimLine_ClaimID  page_count 1,912,404  fragmentation_pct 87.3
BillingCore: 17 nonclustered indexes with 0 reads since restart
Top missing-index hint: dbo.ClaimLine  equality (PayerID) inequality (ServiceDate)
  include (ChargeAmount, Status)  user_seeks 48,210  avg_user_impact_pct 91.4
EDI_Staging heap: dbo.EDI_RawSegment  row_count 212,480,115
Why it matters

Unused indexes slow every insert and update. Missing-index hints are suggestions, not instructions, and must be checked against existing indexes.

Recommendation

Fix the maintenance job first (F-09). Test the missing-index hint. Drop unused indexes only after a full business cycle including month-end. Add a clustered index or purge routine to EDI_RawSegment.

Source: sqlserver/08_index_health.sql
F-15MediumCapacity

SQL Server data drive has about 10 months of room; autogrowth settings are poor

Server(s): SMB-SQL01

The main data drive is filling at roughly 11 GB a month, partly because backup files are kept on it.

Evidence (sample script output)
E:\  total_gb 1000.0  free_gb 118.3  free_pct 11.8   (holds data files and E:\SQLBackups)
BillingCore_Data    growth 1 MB   → Very small fixed growth - review
ClaimsArchive_Data  growth 10 %   → Percent growth - review
Growth (180 days): BillingCore 151.2 → 182.4 GB · ClaimsArchive 382.0 → 418.2 GB
Why it matters

About 67 GB of growth in six months is roughly 11 GB a month, so E: fills in about 10 months — sooner if backup retention grows.

Recommendation

Move backups off E: (also helps F-03). Set fixed growth increments. Size the new server’s storage from this trend plus headroom.

Source: sqlserver/09_disk_file_growth.sql
F-16MediumSupportability

Supported servers are behind on updates

Server(s): SMB-SQL02, SMB-ORA01

The portal and ledger databases are on supported versions, but they have not been kept up to date with released fixes.

Evidence (sample script output)
SMB-SQL02  15.0.4261.1  update_level CU18
SMB-ORA01  dba_registry_sqlpatch latest: 19.18.0.0.230117 Release Update (applied 2023-03-04)
Why it matters

SQL Server 2019 is in extended support until January 9, 2030[4]; check the current build against Microsoft’s list on the day of patching[11]. Oracle 19c is a long-term release; Oracle has announced Premier Support to December 31, 2029[15] (confirm in Oracle’s Lifetime Support Policy). Oracle ships Release Updates quarterly, so 19.18 is several updates behind.

Recommendation

Patch SMB-SQL02 after testing on a copy. Apply the current 19c Release Update to SMB-ORA01 once the ledger vendor confirms it is certified, rehearsing on a clone first.

Source: sqlserver/01_instance_inventory.sql · oracle/01_inventory.sql
F-17MediumSecurity

xp_cmdshell is enabled on the billing server and used by three EDI procedures

Server(s): SMB-SQL01

SQL Server is allowed to run Windows commands, and three claim-import procedures rely on it to move files.

Evidence (sample script output)
xp_cmdshell  configured_value 1  running_value 1
EDI_Staging modules flagged 'xp_cmdshell call': dbo.usp_MoveInboundFiles,
  dbo.usp_ArchiveProcessedFiles, dbo.usp_PurgeOutbound
Why it matters

Combined with sysadmin application logins (F-05), a compromised application could run commands on the server. It is also not available in Azure SQL Database or Managed Instance.

Recommendation

Move the file handling to an SSIS package, a PowerShell job step or the application, then disable xp_cmdshell.

Source: sqlserver/06_configuration.sql · sqlserver/11_upgrade_blockers.sql
F-18MediumOperations

Nobody is notified when a job or backup fails

Server(s): All four

Failures are recorded but no one is told, which is how the backup, integrity and disk problems went unnoticed.

Evidence (sample script output)
SQL Server  sysoperators 0 rows · notify_level_email 0 on all jobs · sysmail_profile 0 rows
PostgreSQL  pg_dump cron job writes to a local log only
Oracle      RMAN scripts run from cron; no failure e-mail configured (per interview)
Why it matters

Silent failure is the common thread behind several findings.

Recommendation

Configure failure e-mails on every backup and maintenance job to a mailbox your IT contact actually reads, plus a simple daily ‘backup age’ report. (GracePath does not provide round-the-clock monitoring; these alerts go to your own team.)

Source: sqlserver/04_agent_job_failures.sql · sqlserver/11_upgrade_blockers.sql
F-19MediumModernization readiness

Items to resolve before moving the billing server

Server(s): SMB-SQL01

None of these is a problem today, but each affects which platform you can move to and how much testing is needed.

Evidence (sample script output)
BillingCore  assembly PdfStamp  permission_set_desc UNSAFE_ACCESS
BillingCore  12 modules reference ClaimsArchive / EDI_Staging (three-part names)
ReportServer / ReportServerTempDB present → SSRS 2016 catalog
ClaimsArchive compatibility_level 110 · dbo.ClaimNote.NoteText ntext · dbo.ClaimImage.Img image
Why it matters

From SQL Server 2017 onward, ‘clr strict security’ requires UNSAFE assemblies to be signed or trusted. Azure SQL Database does not support CLR or cross-database queries, which rules it out for BillingCore as built. There will be no SSRS release after 2022; from SQL Server 2025 on-premises reporting moves to Power BI Report Server, available to SQL Server 2025 Standard and Enterprise customers, and SSRS 2022 is supported until January 11, 2033[9]. Compatibility level 110 is still accepted by SQL Server 2022 and 2025[7], but should be raised deliberately after testing.

Recommendation

Sign or replace the PdfStamp assembly; choose SSRS 2022 or Power BI Report Server with the report owners; keep the three billing databases together; test ClaimsArchive at the target level on a copy; run Microsoft’s migration assessment tooling alongside this review.

Source: sqlserver/11_upgrade_blockers.sql · sqlserver/02_databases.sql
F-20MediumHigh availability

No standby for the billing or ledger databases

Server(s): SMB-SQL01, SMB-ORA01

If either server fails, recovery means rebuilding and restoring from backup, which has never been timed (F-03).

Evidence (sample script output)
SMB-SQL01  IsClustered 0 · IsHadrEnabled 0 · no log shipping configured
SMB-ORA01  database_role PRIMARY · no standby destinations (v$archive_dest) · Standard Edition 2
Why it matters

With a 4-hour RTO for billing, a restore-only plan may be enough if a timed test proves it. If not, a standby is needed. High-availability options and their licensing differ by product and edition.

Recommendation

Decide after the timed restore tests. If restores meet the targets, document and drill them; if not, add a standby (for SQL Server, log shipping or a Basic Availability Group; for Oracle, an option that matches your edition and license) to the new design.

Source: sqlserver/01_instance_inventory.sql · oracle/01_inventory.sql
F-21LowPerformance

PostgreSQL vacuum is falling behind on the main documents table

Server(s): SMB-PG01

Deleted and updated rows are not being cleaned up quickly, so the main table is bigger and slower than it should be.

Evidence (sample script output)
public.document_page  n_live_tup 18,204,551  n_dead_tup 8,177,032  dead_pct 31.0
  last_autovacuum 2026-09-24 03:12
pid 48211  usename docintake_app  state idle in transaction  transaction_age 06:12:44
Why it matters

A session left ‘idle in transaction’ by the intake app stops vacuum from removing old rows anywhere in the database.

Recommendation

Ask the app vendor about the idle transaction; set idle_in_transaction_session_timeout after testing; tune autovacuum for the large table.

Source: postgresql/04_performance_maintenance.sql
F-22LowModernization readiness

Deprecated SQL Server features are in use (warnings, not blockers)

Server(s): SMB-SQL01

Some older coding patterns are still used. They work today but should be cleaned up during migration testing.

Evidence (sample script output)
Deprecated Features counters (38 days): sysdatabases 18,402 · Data types: text ntext or image 9,877 ·
  sysobjects 4,215 · More than two-part column name 1,309 · Table hint without WITH 642 · SET ROWCOUNT 88
Why it matters

Deprecated means scheduled for eventual removal, not removed. None of these is on Microsoft’s list of features removed in SQL Server 2022 or 2025 (for example Data Quality Services and Master Data Services are removed in 2025 and are not installed here)[8].

Recommendation

Log the calling code with an Extended Events session during testing and fix it in the procedures that are touched for the migration anyway.

Source: sqlserver/10_deprecated_features.sql · sqlserver/11_upgrade_blockers.sql

7Recommended path per server

SMB-SQL01 · SQL Server 2016

Migrate side-by-side to SQL Server 2022 or 2025 Standard on a new server

  • Build on a currently supported Windows Server; pick 2022 or 2025 from the billing vendor’s supported-version list.
  • Move BillingCore, ClaimsArchive and EDI_Staging together (they reference each other).
  • Reports: SSRS 2022, or Power BI Report Server with a SQL Server 2025 license.
  • Bridge: if cut-over cannot finish within your accepted risk window, buy ESU for this server via Azure Arc. Pricing from Microsoft or your licensing partner.
  • Azure SQL Managed Instance is a possible later step once xp_cmdshell and the CLR assembly are dealt with. Azure SQL Database and a move to PostgreSQL are not a fit as built (vendor app, CLR, cross-database T-SQL).
SMB-SQL02 · SQL Server 2019

Stay on 2019 for now — patch, encrypt, plan its upgrade

  • Supported until January 9, 2030 — no forced move.
  • Apply the latest update, enable TDE, add off-host backup copies, remove sysadmin from portal_app.
  • Revisit in 2028, or fold into the new SQL Server if sizing allows.
SMB-PG01 · PostgreSQL 14

Fix backups now, then upgrade to PostgreSQL 17 or 18

  • Drop the stale replication slot, set up WAL archiving to separate storage, take a fresh off-host backup.
  • Apply 14.24 as a stop-gap minor update.
  • Upgrade to 17 or 18 (supported to 2029 / 2030) after the intake app vendor confirms support; rehearse with pg_upgrade on a copy.
  • Managed Azure Database for PostgreSQL is an option to evaluate if you would rather not run the server yourselves.
SMB-ORA01 · Oracle 19c

Stay on 19c — patch, tighten access, move backups off the SAN

  • 19c is Oracle’s long-term release; Premier Support announced to December 31, 2029 (confirm with Oracle).
  • Apply the current Release Update once the ledger vendor certifies it.
  • Copy RMAN backups to separate storage; run RESTORE VALIDATE and a timed test restore.
  • Moving the ledger to PostgreSQL or SQL Server only makes sense if the vendor supports it — not recommended now.

8Modernization options considered

SQL Server 2016 (SMB-SQL01)

Microsoft’s end-of-support guidance lists paid Extended Security Updates as a short-term bridge, an upgrade to SQL Server 2025 on-premises or hybrid, and moves to Azure SQL Database, Azure SQL Managed Instance or SQL Server on Azure Virtual Machines[1].

OptionFitMain considerations
Extended Security UpdatesBridge onlyCritical security updates for up to three years (Year 3 ends July 17, 2029)[2]; bought per server in the Azure portal, on-premises servers connected through Azure Arc[3]. Standard edition eligible[3]. Paid — pricing from Microsoft or a licensing partner. Does not fix the Windows Server 2016 deadline.
SQL Server 2022 / 2025 on a new serverRecommendedSupported to 2033 / 2036[5][6]. Side-by-side build on a supported Windows Server. Standard edition includes TDE from 2019 onward[12]. Confirm the billing vendor supports the chosen version.
Azure SQL Managed InstancePossible laterClosest to on-premises SQL Server (Agent jobs, cross-database queries). Needs the xp_cmdshell file handling replaced and the CLR assembly reviewed; running cost to be compared with an on-premises license.
SQL Server on an Azure VMPossibleSame engine, hosted by Azure; Microsoft lists Azure VMs among the environments ESU covers[1]. Useful if you want to leave your own hardware.
Azure SQL DatabaseNot a fit as builtNo cross-database queries, CLR or SQL Agent in the same form — BillingCore depends on all three.
Re-platform to PostgreSQLNot a fitThe billing software is a vendor product built for SQL Server (T-SQL procedures, CLR, SSRS). Only worth considering if the vendor offers a PostgreSQL edition.

PostgreSQL 14 and Oracle 19c

OptionFitMain considerations
PostgreSQL 14.24 minor updateStop-gapSame major version, no data conversion; still loses fixes on November 12, 2026[13].
PostgreSQL 17 or 18RecommendedSupported to November 2029 / November 2030[14]. pg_upgrade rehearsal on a copy; confirm intake app support.
Azure Database for PostgreSQL (managed)EvaluateRemoves server upkeep; check the app’s extensions and network requirements and compare running cost.
Oracle 19c + current Release UpdateRecommendedLong-term release; Premier Support announced to December 31, 2029[15]. Vendor certification of the RU first.
Oracle next long-term releaseLaterWhen the ledger vendor certifies it; plan with Oracle’s AutoUpgrade tool.
Re-platform ledger to PostgreSQL / SQL ServerNot nowOnly with vendor support; large testing effort for little near-term gain.

9Phased roadmap

Week numbers are illustrative and start when work is approved. Phases overlap on purpose.

Phase 0

Stabilise

Weeks 1–2
  • Fix PostgreSQL disk and backups (stale slot, fresh off-host dump)
  • Add SQL Server log backups; reclaim log space
  • Copy all backups off-host on every platform
  • First timed restores: BillingCore, docintake, LEDGERPDB
  • Failure e-mails to your IT contact
Phase 1

Access & security

Weeks 2–5
  • User access clean-up: named admins, app logins off admin roles, shared accounts split, orphaned/unused accounts locked then removed
  • Disable sa; lock DBSNMP; SCRAM + SSL on PostgreSQL
  • TDE and backup encryption on SMB-SQL02
  • Password and lockout rules on all platforms
Phase 2

Patch & tune

Weeks 3–7
  • SMB-SQL01 to SP3 + final update; memory, MAXDOP, tempdb
  • SMB-SQL02 latest update
  • PostgreSQL 14.24; Oracle current RU (vendor-certified)
  • Re-enable CHECKDB; fix index job
Phase 3

Modernize

Weeks 6–14
  • SMB-SQL01 → SQL Server 2022/2025 on new server (ESU decision point first)
  • SMB-PG01 → PostgreSQL 17/18
  • Rehearsal migrations with timing; cut-over in agreed windows
  • Decommission old SQL Server 2016 host
Phase 4

Review

Quarterly
  • Health & access review with the same read-only scripts
  • Restore drill against the RTO
  • Short written report and updated roadmap

10Level 3 — what GracePath would do next

This report covers Level 1 (Health & Access Check) and Level 2 (Modernization Plan). Level 3 is scoped implementation, agreed in writing before anything on the servers is changed. Each package is quoted per project, based on the number of servers, the change windows available and who does the hands-on work. GracePath does not provide round-the-clock monitoring or managed security services.

Want this for your own databases?

The Database Health, Access & Modernization Review uses the same read-only approach for SQL Server, Oracle, PostgreSQL and Azure SQL. Price and turnaround are confirmed in your quote.

11References and notes

Vendor facts in this report were checked against the sources below on October 22, 2026. Where only a secondary source could be reached, it is marked as such. Lifecycle dates and edition rules change; re-check them before making a decision.

  1. Microsoft SQL Server Blog — “SQL Server 2016 end of support is here: Plan your next steps” (July 14, 2026). https://www.microsoft.com/en-us/sql-server/blog/2026/07/14/sql-server-2016-end-of-support-is-here-plan-your-next-steps/
  2. Microsoft Lifecycle — SQL Server 2016 (service packs, end of extended support, ESU Years 1–3). https://learn.microsoft.com/lifecycle/products/sql-server-2016
  3. Microsoft Lifecycle FAQ — SQL Server Extended Security Updates (up to three years; Azure Arc; Enterprise/Standard only). https://learn.microsoft.com/en-us/lifecycle/faq/sql-server-extended-security-updates
  4. Microsoft Lifecycle — SQL Server 2019. https://learn.microsoft.com/en-us/lifecycle/products/sql-server-2019
  5. Microsoft Lifecycle — SQL Server 2022. https://learn.microsoft.com/lifecycle/products/sql-server-2022
  6. Microsoft Lifecycle — SQL Server 2025. https://learn.microsoft.com/en-us/lifecycle/products/sql-server-2025
  7. Microsoft Learn — ALTER DATABASE compatibility level (supported levels per version). https://learn.microsoft.com/en-us/sql/t-sql/statements/alter-database-transact-sql-compatibility-level
  8. Microsoft Learn — Discontinued Database Engine functionality (DQS and MDS removed in SQL Server 2025). https://learn.microsoft.com/en-us/sql/database-engine/discontinued-database-engine-functionality-in-sql-server
  9. Microsoft Learn — Reporting Services consolidation FAQ (no SSRS after 2022; Power BI Report Server). https://learn.microsoft.com/en-us/sql/reporting-services/reporting-services-consolidation-faq
  10. Microsoft Windows Server Blog — “Planning ahead for Windows Server 2016 end of support” (ends January 12, 2027). https://www.microsoft.com/en-us/windows-server/blog/?p=8436
  11. Microsoft Support — KB4518398, SQL Server 2019 build versions. https://support.microsoft.com/help/4518398
  12. SQLServerCentral — “TDE in Standard Edition on SQL 2019” (secondary source). https://www.sqlservercentral.com/blogs/tde-in-standard-edition-on-sql-2019
  13. PostgreSQL Global Development Group — postgresql.org home page (PostgreSQL 14 stops receiving fixes on November 12, 2026; current minor releases incl. 14.24). https://www.postgresql.org/
  14. endoflife.date — PostgreSQL release support dates (secondary source; 17 to Nov 8, 2029; 18 to Nov 14, 2030). https://endoflife.date/postgresql
  15. The Register — “Oracle extends 19c database support to 2032” (Feb 18, 2025; secondary source — confirm in Oracle’s Lifetime Support Policy). https://www.theregister.com/2025/02/18/oracle_extends_19c_support/

About this sample

Saguaro Medical Billing LLC (Sample), its people, servers, accounts, databases, numbers and interview answers are fictional and were written to show the format and depth of a GracePath Ventures review. They are not taken from any real client. The evidence blocks show what the read-only script packs are designed to return; the scripts themselves are shared only with clients as part of an engagement. This report is not legal, compliance, licensing or tax advice.

Sample report — fictional company and data