gtmjosh

How to audit GTM systems technical debt

· 25 min read· Salesforce · HubSpot· Platform behavior verified September 8, 2026

A practical RevOps framework for auditing GTM systems, CRM health, deployment hygiene, AI governance, data quality, ownership, dependencies, cost, and migration risk.

On this page

A GTM systems audit should not answer "how complicated is our stack?" It should answer a harder question:

Which complexity is earning its keep, which complexity is creating risk, and what should we do about it next?

Almost every mature GTM stack looks messy from far enough away. There are old fields, overlapping automations, reports nobody remembers building, integrations with confusing names, custom code, spreadsheets, vendor tools, and processes that grew one reasonable request at a time. The mistake is assuming that the count of those things tells you whether the system is healthy.

A useful audit moves through six questions:

  1. Inventory: what actually exists?
  2. Verify: what is active, used, healthy, and load-bearing?
  3. Contextualize: why does it exist, and what business process does it support?
  4. Quantify: what does it cost in money, time, risk, and operating friction?
  5. Decide: keep, retire, replace, simplify, rebuild, or investigate?
  6. Sequence: what should happen now, next quarter, before renewal, or only when another dependency moves?

The output is not a long list of everything imperfect. It is a decision system for improving the stack.

An audit is not a complexity contest

A weak audit often starts like this:

487 custom fields
142 automations
63 integrations
8,200 reports
29 installed packages
316 failed jobs

Those numbers sound alarming because they are large, but they tell leadership almost nothing on their own. Ask the question behind each count instead:

How many fields are actually populated, referenced, or used by a process?
How many automations are active, and which ones execute?
Which integrations moved data in the last 90 days?
Which reports are opened or feed another operating process?
Which packages are load-bearing versus abandoned?
What percentage of jobs failed, and did one known issue cause most of them?

A count without operational context is not a finding. A system with 300 automations can be healthy; a system with 20 can be dangerous. The number becomes useful only after you understand activity, ownership, dependency, failure rate, and business impact.

Rates beat scary raw counts

Suppose a background system produced 250 failed jobs last week. If it executed 500 jobs, the system is on fire. If it executed 80,000 jobs and nearly every failure came from one known edge case, the operating conclusion is completely different.

Use denominators:

Weak metricBetter metric
250 failures250 / 80,000 executions = 0.31% failure rate
4,000 stale Contacts4,000 / 55,000 marketable Contacts = 7.3% stale
90 unused fields90 / 620 reviewed fields = 14.5% retirement candidates
12 dormant integrations12 / 45 external connections = 27% under review

Rates do not eliminate judgment. One failed job that blocks every demo request can matter more than 1,000 harmless retries. The denominator simply stops the raw number from doing the thinking for you.

Use the right evidence for the thing you are auditing

"No usage" is not one metric. An externally authenticating connected app might produce OAuth activity; an in-platform managed package may never log in through OAuth at all. A scheduled integration can run quietly once a month and still be load-bearing, while a heavily provisioned app can have thousands of records and no active business process.

Choose evidence that is capable of proving or disproving the behavior you care about. Useful evidence includes authentication history, API traffic, scheduled-job execution, workflow logs, record writes, report usage, licence activity, dependency metadata, contracts, invoices, and user interviews when telemetry cannot answer the question.

A zero in the wrong metric creates false confidence.

Build the evidence pack before writing findings

The critique I would make of most technical audits is not that they lack categories. It is that they never show the operator how to collect the evidence. Below is the minimum runbook I would use before writing an executive summary.

Salesforce: start with Setup Audit Trail

Setup Audit Trail is one of the fastest ways to understand how much production configuration is changing, who is changing it, and which areas of Setup are moving. Salesforce retains the downloadable setup history for 180 days.

Platform behavior · source

Salesforce Setup Audit Trail records recent setup changes, including changes to Apex, Lightning components and pages, flows, permissions, packages, and other configuration. Salesforce documents a 180-day downloadable history.

You can export it from Setup → View Setup Audit Trail, or query it when that is more convenient:

Recent Salesforce setup changes
SELECT
  CreatedDate,
  CreatedById,
  Section,
  Action,
  Display,
  DelegateUser
FROM SetupAuditTrail
WHERE CreatedDate = LAST_N_DAYS:90
ORDER BY CreatedDate DESC

Do not summarize this as "347 setup changes." Classify the rows. Which were deployments, emergency production edits, permission changes, package changes, flow edits, and user administration? Who made them? Can the metadata changes be traced to a source-control commit or approved release?

Salesforce: check API usage with the right layer

For capacity, make the first check executable instead of writing "review API usage" in a checklist:

Salesforce org limits
sf org list limits --target-org prod --json
Platform behavior · source

Salesforce CLI's org list limits command returns each org limit's maximum allocation and remaining allocation. Use those fields explicitly instead of guessing whether a dashboard number represents used or remaining capacity.

For a returned limit, calculate used = maximum - remaining, then carry the denominator and observation time into the finding. That sounds obvious, but in a real audit it prevents one of the easiest mistakes to make: turning a healthy "remaining" value into a scary "used" value or vice versa.

If Event Monitoring is licensed, query EventLogFile to understand which API families and clients are actually generating traffic:

API-related Salesforce event logs
SELECT LogFile, EventType, CreatedDate
FROM EventLogFile
WHERE EventType IN ('API', 'RestApi', 'BulkApi', 'ApiTotalUsage')
  AND CreatedDate = LAST_N_DAYS:7
ORDER BY CreatedDate DESC
Platform behavior · source

Salesforce Event Monitoring exposes detailed security, performance, and usage data and supports querying event logs. Detailed Event Monitoring requires Salesforce Shield or the Event Monitoring add-on.

If you do not have Event Monitoring, that is not a reason to skip API health. Combine the org limits with middleware logs, integration-user history, vendor logs, and write patterns in the CRM. The evidence pack should state which visibility you did and did not have.

Salesforce: inspect async health with SOQL

A raw failed-job count is nearly useless without the executed-job denominator and failure concentration. Pull the jobs first:

Recent asynchronous Apex jobs
SELECT
  JobType,
  Status,
  NumberOfErrors,
  JobItemsProcessed,
  TotalJobItems,
  CreatedDate,
  CompletedDate
FROM AsyncApexJob
WHERE CreatedDate = LAST_N_DAYS:30
ORDER BY CreatedDate DESC

Group by job type and status outside the query if that makes the failure-rate math easier. Then isolate recurring failures by class, schedule, integration, or business process. A small number of repeated failures from one known component calls for a different remediation plan than broad instability across the async layer.

Salesforce: measure field population instead of guessing field usage

Do not treat "we have a lot of fields" as evidence that the schema is bad. For important objects, calculate population against the eligible population, not necessarily every historical record.

Example account field fill rates
SELECT
  COUNT(Id) total_accounts,
  COUNT(Industry) with_industry,
  COUNT(AnnualRevenue) with_revenue
FROM Account
WHERE IsDeleted = false

For a custom field, substitute the API name. If the field is expected only on enterprise customers or open Opportunities, change the WHERE clause so the denominator matches the business rule.

Salesforce currently does not provide a native report that automatically gives population rate for every field on an object, so do not present a generic "field usage" screen as stronger evidence than it is. Use targeted aggregate queries, dependency checks such as Where is this used?, metadata inspection, and automated scripts when you need object-wide analysis.

Platform behavior · source

Salesforce documents that there is no built-in report type that shows field population rate across an object. Field population must be analyzed through another method.

HubSpot: export the schema with usage and fill rate

HubSpot gives you a useful evidence pack without writing code. In Settings → Properties, use Export all properties for the objects you are auditing.

Platform behavior · source

HubSpot's property export includes property metadata, usages, fill rate, and, for contact, company, deal, and ticket properties, the last updated time and update source. Individual property-definition exports also include the HubSpot tools where the property is used.

That export is useful for separating low-fill fields that are truly obsolete from low-fill fields that are intentionally narrow. For a suspicious property, export its property history with source information so you can see which user or tool is actually writing it. HubSpot's Data Model Health Check and Data Quality tools can also surface low-fill, inactive, similar, and unused configuration as leads for investigation.

The point is not to prove that one CRM has better tooling. It is to get to evidence before recommendations.

Download the audit templates

The tables below explain the framework, but an audit template should be something you can actually open in a spreadsheet.

The first is for the stack-level inventory and disposition. The second is for the deeper CRM review, with columns for evidence source, query/tool, denominator, finding, risk, owner, action, and cadence.

Start with a stack-level inventory

The stack audit should cover more than software invoices. Inventory the systems that sit in, around, and on top of the CRM: marketing automation, sales engagement, conversation intelligence, CPQ, customer success, enrichment, BI, document systems, collaboration integrations, standalone spreadsheets, custom applications, APIs, middleware, serverless jobs, AI providers, and privileged admin utilities.

A fictional stack might include Salesforce, Marketo, Salesloft, Looker, PandaDoc, a custom territory service, and several operational Google Sheets. Do not stop at the vendor name; the audit needs the reason each capability exists.

FieldWhat you are trying to learn
System / capabilityWhat is being evaluated
Business purposeThe operating problem it solves
Business ownerWho decides whether the capability is still needed
Technical ownerWho can maintain or change it
Data in / data outWhich customer, prospect, financial, or employee data crosses the boundary
Authentication / credentialsHow privileged access is granted and owned
Usage evidenceThe signal that proves whether it is active
Cash costVendor spend and incremental software cost
Internal operating costAdmin, troubleshooting, enablement, and maintenance time
Critical dependenciesWhat breaks if this disappears
OverlapWhich other system already provides similar capability
PortabilityWhat happens if the CRM or surrounding platform changes
RiskSecurity, reliability, data, continuity, or process risk
DispositionKeep / retire / replace / simplify / investigate
Next actionConcrete owner and step
WhyEvidence behind the recommendation
ConfidenceVerified versus inferred conclusion

"Retire Tool X" creates an argument. "Retire Tool X because it has no qualifying activity, its contract overlaps with Tool Y, no active workflow references it, and the technical owner confirmed there is no dependent process" creates a decision.

Then go deeper inside the CRM

The stack inventory tells you which systems exist. It does not tell you whether the CRM itself is healthy. I would inspect at least these eight areas.

1. Capacity and platform limits

Check the limits capable of becoming actual operating constraints: storage, API usage, async processing, object-specific ceilings, licence capacity, and schema limits. Verify whether every number means used, remaining, allocated, or available before turning it into a red flag, and reconcile suspicious values against a second signal.

A capacity finding should read like this:

Observed: 72% of file storage used
Trend: +4 percentage points per quarter
Estimated runway: ~7 quarters at current growth
Business impact: new attachments fail when the limit is reached
Recommendation: archive historical files before Q2
Confidence: VERIFIED

That is much more useful than "storage at 72%."

2. Automation landscape

Map modern workflow automation, legacy workflow engines, Apex or custom code, scheduled jobs, middleware, and external automation separately. For each production automation, capture active state, trigger, records touched, owner, execution evidence, duplicate logic, failure behavior, and retirement dependencies.

The important distinction is between metadata that exists and logic that still runs. "We have 120 workflows" is inventory. "Forty are live, 55 are inactive history, 15 are migration artifacts, and 10 still write production fields" is actionable.

3. Code and async health

For custom code, look beyond test coverage percentage. Identify which classes execute in customer-facing or revenue-critical paths, which scheduled components fail, whether retries are bounded, whether errors are observable, and whether another competent operator can maintain the code.

A blanket "raise test coverage" project can burn weeks without reducing meaningful risk. Prioritize code by operating criticality, change frequency, failure blast radius, and whether a test would actually protect a business contract.

4. Data quality and database hygiene

A large CRM database is not inherently valuable. A useful database contains people and companies you can responsibly and productively work, with enough history to support the business and legal retention requirements.

Review duplicates, invalid email data, records outside the ICP, stale records with no meaningful engagement, inactive owners, missing persona and company-fit data, consent/suppression state, enrichment freshness, Opportunity hygiene, and record populations that no longer belong in operational reporting.

Dirty databases create second-order costs. Stale or invalid people hurt deliverability if they remain marketable; bad-fit records inflate leadership's picture of the addressable base; and enrichment programs waste credits maintaining records the business should no longer be working. A smaller governed population is often cheaper to enrich and easier to reason about.

Do not delete records simply because they are old. Define a retention and eligibility policy that considers fit, recent engagement, customer history, consent, legal requirements, and legitimate future value. The CRM data quality audit covers this measurement layer in more detail.

5. Schema, access, and user experience

Review field population and dependencies, duplicate business concepts, picklist ownership, deprecated fields still exposed to users, permissions, profiles/roles/teams, record-page density, save-time friction, and admin-only controls.

Field count is not automatically technical debt. A field nobody trusts, nobody owns, and three automations still write is. Conversely, a narrow field with 5% population can be healthy if it is intentionally required only on a 5% subset of records. This is why the denominator and business definition belong beside the count.

6. Installed packages, apps, and privileged utilities

Classify each package or connected utility as active/load-bearing, active but replaceable, dormant but harmless, dormant and privileged, redundant, retirement-gated, or unknown. The unknown category deserves attention because an integration nobody can explain should not quietly keep privileged access forever.

For external apps, review authentication history, API calls, record writes, credentials, data exposure, contract owner, and renewal date. For in-platform packages, use evidence appropriate to how the package operates rather than interpreting zero OAuth logins as zero usage.

7. Deployment and release hygiene

This belongs near the top of a CRM debt audit because it determines whether every other improvement is safe to make.

Ask:

  • Is production metadata represented in source control?
  • Do changes normally move through pull requests or an equivalent review path?
  • Can you trace a production change to the commit, ticket, and person who approved it?
  • Are admins editing production directly as the normal workflow?
  • Is there a documented hotfix path for genuine emergencies?
  • Are sandboxes or test environments used for meaningful changes?
  • Do deployments run validation or tests before production?
  • Can you identify what changed in a release and roll it back?
  • Are secrets and integration credentials kept outside source files?
  • Are permission changes included in deployment governance or handled ad hoc?

Use Setup Audit Trail as one side of the evidence and Git/CI/deployment history as the other. Sample a meaningful set of production metadata changes from the last quarter and try to trace each one to a governed release record.

A useful metric is:

untraceable production metadata changes / sampled production metadata changes

Do not aim for an artificial 0% if your platform or vendor creates legitimate system changes. Investigate the exceptions and label them. The red flag is an operating model where nobody can explain whether a change was deliberate, reviewed, or reproducible.

A mature small team does not need enterprise release bureaucracy. It does need a path that makes production reproducible.

8. AI agents and automated decisions

An AI surface should not get a one-line audit check. It can read more data, make fuzzier decisions, and acquire broader action permissions than a traditional workflow, so the audit has to cover authority, context, and failure behavior explicitly.

Start by inventorying every AI capability that can touch GTM data: vendor copilots, CRM agents, internal retrieval tools, enrichment models, scoring/classification services, email generation, routing recommendations, and agents with tools that can write records or trigger downstream actions.

Then review each surface across these dimensions:

DimensionAudit question
AuthorityCan it read, recommend, draft, write, or execute? Which actions require approval?
Decision ownershipIs the model advisory, or can it become the operational source of truth? Who can override it?
ContextWhich CRM records, documents, transcripts, websites, and memory/context sources can it read?
Data exposureWhich data leaves the CRM, and which provider receives it? Are sensitive fields excluded?
Prompt / rule ownershipWhere are system prompts, rules, examples, and thresholds stored? Are they versioned?
Model / providerWhich provider and model are used? What happens when the model changes?
ToolsWhich APIs or write actions can the model invoke? Are tool permissions narrower than the human admin's?
Deterministic gatesWhich hard business rules run before and after model judgment?
FallbackWhat happens on timeout, provider outage, malformed output, low confidence, or missing context?
ObservabilityCan you reconstruct model version, prompt/rule version, evidence, tool calls, latency, cost, and final action?
EvaluationIs there a golden set, shadow mode, override data, or another way to detect regressions?
CostAre token/API consumption, concurrency, retries, and per-record cost bounded?

The most important question is what authority the agent has when it is wrong. A summarizer that produces a poor paragraph and an agent that can reassign an Opportunity are not the same risk tier.

I prefer an explicit ladder:

Read -> Recommend -> Draft -> Write -> Execute

Every AI surface should be able to justify why it sits where it does on that ladder. If the agent writes or executes, inspect the deterministic eligibility gates around the action and the human-review path for exceptions. The deterministic rules versus AI judgment pattern defines that authority boundary, and the CRM AI control plane covers prompt/model/tool versioning, usage, and failure handling in more depth.

A useful AI finding is not "we use three models." It is closer to: "One outbound research agent can read all Account notes and write a recommendation field; its prompt is versioned, write scope is limited to one field, failures fall back to no-write, usage is logged, but the retrieval layer exposes customer notes that are not required for the decision." That is a finding someone can act on.

Custom does not mean debt

The lazy version of a systems audit says custom = bad and native = good. Real systems do not work that way.

A custom application with strong usage, a named owner, tests, monitoring, documentation, controlled deployment, and measurable business value may be perfectly healthy architecture. A native integration nobody uses, understands, or owns can be technical debt.

Evaluate custom systems with the same questions as purchased systems: Is the capability needed? Who relies on it? What does it replace? Is it observable? Can another operator administer it? What is the maintenance cost and failure blast radius? Would the native alternative genuinely simplify the process, or would it move complexity somewhere less visible?

Technical debt is complexity whose carrying cost is no longer justified by the value it creates. That can be custom code, a vendor contract, a workflow nobody will touch, a spreadsheet everyone depends on, or a temporary exception process that became permanent.

Map dependencies before you retire anything

The easiest way to break a GTM system is to remove something because it looks unused without understanding what depends on it. Build the dependency chain before making the retirement decision:

Web form
  -> marketing automation
  -> CRM campaign + Contact
  -> qualification workflow
  -> SDR queue
  -> Opportunity
  -> BI pipeline report

A connector with low direct usage may still be the only thing creating records that feed that chain. For every retirement candidate, identify what reads from it, what writes through it, what identity/key it supplies, which reports assume its data exists, which teams notice first when it stops, whether it can be disabled safely before deletion, and whether another migration gates the retirement.

Something can be absolutely destined for retirement and still be absolutely unsafe to remove today. The handoff contracts between systems pattern is useful when the dependency crosses tools or teams.

Audit cash cost and internal time separately

Vendor cost is visible because it has an invoice; internal implementation cost is easy to pretend is free because it already sits inside payroll. For any major remediation or migration, estimate both.

Cash cost includes licences, new software, agency hours, hosting, migration/archive costs, and temporary dual-running. Internal cost includes discovery, business-rule explanation, scope decisions, data cleanup, mapping, reconciliation, stakeholder coordination, technical review, UAT, training, cutover, hypercare, and ongoing ownership.

An implementation partner can reduce internal build effort, but it does not eliminate internal work. Someone inside the company still has to explain why the current process exists, decide which exceptions matter, validate what the partner built, and own the result afterward. A migration estimate that prices only agency hours is a cash estimate, not a total-effort estimate.

A migration is a chance to reduce debt, not copy it

Do not start a CRM migration with "How do we recreate everything we have today?" Start with "What is the minimum system we need to run the business honestly on day one?"

Classify each existing capability:

DecisionMeaning
RebuildThe business genuinely needs the capability and the target does not provide it adequately
Configure nativeThe target's standard behavior is good enough
ReplaceAnother existing or new tool is a better owner
RetireThe capability no longer earns its keep
DeferUseful, but not required for cutover
InvestigateEvidence is insufficient to decide

This is where migration planning gets hard. Building is often easier than deciding what deserves to survive because people know how the current system behaves without necessarily knowing which behavior is intentional, which exists because of an old request, which compensates for another system, and which nobody would miss.

Treat that discovery work as part of the migration. The leanest useful migration rebuilds demonstrably required business capability, accepts platform defaults where they satisfy the contract, and postpones noncritical parity until the new core is stable. That does not mean blindly moving to vanilla software; a genuinely load-bearing custom capability may still be the simplest honest thing to rebuild.

How to audit debt you helped create

Most internal operators are not reviewing a stranger's pristine architecture. They are auditing a system they inherited, extended, or partly built themselves. That creates two opposite biases: defending old work because you remember why it exists, and overcorrecting because you feel embarrassed that it exists at all.

Use the original context as evidence, not as a verdict. For each material piece of debt, write five things:

Original constraint: Why was this built?
Current constraint: Does that reason still exist?
Current value: What does it still enable?
Current carrying cost: What time, risk, spend, or friction does it create?
Decision: Keep, simplify, retire, replace, or investigate?

A workaround built during a deadline may have been the correct choice at the time. Three years later it can still deserve retirement. Both statements can be true.

For high-consequence decisions, have another operator or stakeholder review the evidence. Ask users what would break if the capability disappeared; ask leadership whether the business rule still exists; and show the recommendation before you execute it. This prevents the audit from becoming either a defense of your architecture or a cleanup project designed to erase your fingerprints.

The healthiest self-audit question is: if I inherited this today with no emotional attachment to it, what evidence would I need before deciding whether it stays?

Use the audit to produce a roadmap, not a shame list

Every audit finds more work than the team can do. Prioritize findings by urgency, business impact, effort, and dependency rather than by how ugly the configuration looks.

TimingType of work
NowCapacity cliffs, broken customer-facing paths, security exposure, repeated high-impact failures
30 daysDormant privileged tools, clear redundancies, cheap hygiene fixes
QuarterAutomation consolidation, schema cleanup, deployment improvements, database hygiene, bounded technical debt
Before renewal / migrationVendor overlap, portability, licensing, rebuild-or-retire decisions
BacklogCosmetic debt with low operating impact

The audit should leave every material action with an owner, evidence, and a reason. If the recommendation is only "this looks messy," it is not ready for the roadmap.

Turn repeat findings into preventive controls

Quarterly cleanup is useful, but finding the same problem every quarter means the upstream process needs to change. If each database audit finds another large population of non-ICP Contacts, trace which source keeps creating them, why they are eligible for enrichment or marketing, and whether the form, import, enrichment, or routing policy should change.

The same applies to Opportunity hygiene, duplicate creation, stale ownership, failed jobs, and field sprawl. The mature loop is:

finding -> root cause -> control -> next audit proves whether the control worked

Each audit should make the next audit different.

Put GTM systems health on a recurring cadence

A one-time audit decays immediately because the stack keeps changing. Use different cadences for technical health and process alignment.

Continuous: monitor known failure modes

Automate checks for integration failures, job failures, capacity thresholds, duplicate creation, SLA misses, enrichment failures, unowned records, and reconciliation mismatches. Continuous monitoring answers whether a known bad thing happened again; it does not replace the deeper audit.

Quarterly: systems and database hygiene

At least once a quarter, deliberately inspect Lead/Contact fit and activity, stale/invalid records, duplicates, field usage and retirement candidates, Opportunity hygiene, integration usage, failed-job trends, enrichment efficiency, dormant reports/workflows/packages, production-change traceability, AI-surface permissions, and previous-quarter remediation.

Database maintenance compounds. A company that consistently removes invalid, stale, and clearly bad-fit records under a governed policy gets a more honest picture of who is actually addressable and can materially reduce recurring enrichment work. The goal is not a small database for its own sake; it is a database whose size means something.

Twice a year: process hygiene with leadership

Technical audits cannot tell you whether the business still agrees with the process being automated. At least twice a year, revalidate ICP and target-account criteria, persona definitions, lead scoring, lifecycle stages, Sales Ready handoffs, SDR/AE responsibilities, Opportunity stages, routing, attribution, forecast definitions, and core reporting definitions with the stakeholders who own them.

This catches governance drift. A CRM can execute an obsolete process flawlessly, and that is still a broken operating system. Do not assume leaders remember every lifecycle rule because someone approved it years ago; explain the current contract, show how it behaves, ask what changed, and document the new agreement.

Event-driven: audit before irreversible decisions

Run a focused audit before major renewals, CRM migrations, acquisitions, business-unit consolidation, large tooling purchases, major Sales/Marketing reorganizations, or new AI/data-platform rollouts. Those are the moments when undocumented dependencies become expensive.

CRM-depth checklist

Use the downloadable CSV for the working version. This table is the quick reference for what each row should contain.

AreaInspectContext to capture
CapacityStorage, API, async, licences, object limitsUsed vs remaining, trend, business impact of hitting the limit
AutomationFlows, workflows, triggers, jobs, middlewareActive state, execution, duplicate logic, owner, failure rate
CodeCritical classes, tests, schedulersBusiness path, change frequency, tests, monitoring, maintainer
Data qualityDuplicates, stale records, bad fit, missing fields, ownershipDenominator, eligibility policy, root cause, downstream impact
EnrichmentCoverage, freshness, provider calls, spendEligible population, credit efficiency, overwrite rules
SchemaFields, objects, picklists, deprecated statesPopulation, business definition, writers/readers, retirement path
AccessRoles, permissions, admin utilities, connected appsActive users, privileged surface, owner, necessity
UXLayouts, pages, save time, densityUser impact rather than component count
ReportingReports, dashboards, metric definitionsActual use, source of truth, duplicated numbers
Packages / appsInstalled software and utilitiesUsage evidence, dependencies, privilege, overlap, contract
IntegrationsInbound/outbound sync and APIsData movement, identity, retries, reconciliation, failure behavior
DeploymentSource control, PR/review, CI, hotfixes, rollbackTraceable production changes, reproducibility, release ownership
AIModels, prompts, tools, context, automated decisionsData exposure, authority, versioning, cost, monitoring, fallback, review
Process governanceLifecycle, routing, sourcing, forecasting, ownershipCurrent stakeholder agreement and last-confirmed date

Process-health checklist

A systems audit without the process layer can optimize machinery that should no longer exist. For each major GTM process, record the owner, technical owner, last-confirmed date, and answers to these questions:

process-health-review.yaml
process: Lead-to-opportunity handoff
business_owner: Revenue leadership
technical_owner: RevOps
last_confirmed: YYYY-MM-DD
 
questions:
  - Does the business still agree with the purpose?
  - Are the entry and exit criteria still correct?
  - Do the current ICP and personas still match strategy?
  - Does each team understand its responsibility?
  - Are SLAs realistic and measured?
  - Are rejection / recycle paths still useful?
  - Does the CRM implement the documented rule?
  - Do reports measure the same definition?
  - Which exceptions occurred since the last review?
  - What should change before the next review?

"Nothing changed" is a valid outcome. It means the process is current rather than merely old.

The final audit output

Leadership does not need every query you ran, but you should be able to produce the evidence behind every material conclusion. The final package should contain:

  1. Executive read: what is healthy, what is risky, and what actually matters.
  2. Evidence: numbers with denominators, source, date, and enough context to interpret them.
  3. Decision table: keep, retire, replace, simplify, rebuild, or investigate.
  4. Dependency notes: what cannot move yet and why.
  5. Cost: cash plus internal time.
  6. Roadmap: now / 30 days / quarter / event-driven.
  7. Open questions: unknowns capable of changing the recommendation.
  8. Confidence: verified versus inferred findings.
  9. Cadence: when the relevant layer gets reviewed again.

A good audit makes the system feel smaller even before any software is removed. It turns a pile of fields, vendors, jobs, reports, permissions, agents, and exceptions into named capabilities with evidence, owners, and decisions.

That is how RevOps reduces technical debt: not by deleting customization until the stack looks clean, but by making complexity prove why it deserves to stay.

Primary platform sources

Platform behavior above was re-checked against Salesforce and HubSpot documentation on September 8, 2026. Feature and licence availability can vary by edition.

FAQ

How often should RevOps audit GTM systems?
Run automated health checks continuously where possible, perform a structured systems and database hygiene review at least quarterly, and revalidate major business-process definitions with leadership at least twice a year. Add event-driven reviews before large renewals, migrations, acquisitions, or major operating-model changes.
Is customization the same as technical debt?
No. Customization is debt when its maintenance cost, risk, or complexity no longer earns its keep. A well-owned custom system with real usage, monitoring, tests, documentation, and controlled deployment can be healthier than a native workaround nobody understands or uses.
What should a GTM tech audit measure?
Measure what exists, why it exists, who owns it, whether it is actually used, which data and credentials it touches, what depends on it, how changes reach production, what it costs in cash and internal time, how healthy it is, and what happens if you retire or migrate it. Counts without that context are inventory, not findings.
What Salesforce tools should I use for a CRM health audit?
Start with Setup Audit Trail, sf org list limits, targeted SOQL, AsyncApexJob, metadata and dependency review, and EventLogFile when Event Monitoring is licensed. Use field-population queries and dependency evidence rather than treating raw field count as field usage.
Should a CRM migration rebuild everything from the old system?
Usually no. A migration is a chance to decide what still deserves to exist. Rebuild the minimum capability the business actually needs, use native defaults where they are good enough, and deliberately retire dead or low-value complexity. The hard part is proving what is truly required before cutover.
Does using an implementation agency remove the internal cost of a migration?
No. An agency can absorb configuration and build work, but internal operators still explain business logic, resolve ambiguity, make scope decisions, validate data and mappings, coordinate stakeholders, run UAT, approve tradeoffs, and own the system after launch. Model that time explicitly.
How do I audit a system when I built some of the technical debt myself?
Separate the original reason from the current value. Document what the design solved when it was created, verify whether that constraint still exists, quantify the current carrying cost, and have another stakeholder review high-consequence keep-or-retire decisions. The goal is not to defend or condemn old work; it is to decide what the business needs now.

Get the next guide

New guides and the occasional note on GTM tooling. Don't worry, I won't drop you into a three-month nurture.