# Which SaaS acquisition red flags should stop a deal?

> Twelve SaaS acquisition red flags that expose hidden code forks, owner risk, weak releases, and costs that should stop or reprice a deal.

A SaaS deal should stop or change price when the buyer cannot establish one authoritative codebase, transfer operational control, and reproduce a release without the seller's indispensable engineer. Revenue growth does not cancel those findings. It merely makes the repair more expensive to schedule.

I have watched buyers spend weeks debating framework age while ignoring the facts that determine whether they own a working company on day one. A six-year-old framework can be a manageable backlog item. A private fork on a departing developer's account, an untested restore, or one person who alone can deploy is an immediate transfer risk. The distinction is simple: ordinary debt slows future work; acquisition debt can interrupt today's revenue before the buyer learns where the switches are.

Technical diligence therefore needs a stop-or-reprice rule before the data room opens. A stop finding means ownership, legality, security, or continuity cannot be established on the deal timetable. A reprice finding has a bounded remedy that the buyer can cost, schedule, and verify. Anything described as "we will sort it out after close" belongs in one of those two columns, not in a hopeful third column.

## The evidence must survive the seller's screen share

A buyer needs evidence collected from the systems themselves, not a guided tour of selected dashboards. Ask for read-only access or supervised exports from source control, cloud accounts, identity providers, CI systems, incident tools, billing systems, and support queues. Slides can explain an architecture, but they cannot prove who can deploy it or which repository produced the running build.

Begin with an evidence index. For every claimed production service, record its source repository, default branch, deployment workflow, runtime account, data store, on-call owner, recovery procedure, and current version identifier. Leave a field blank when the seller cannot answer. Blank cells are findings because they reveal where the operating model depends on memory.

The request should include raw inventories, not screenshots: organization repositories with fork and archive status, branch protection settings, identity memberships, privileged roles, recent workflow runs, cloud resources by account, database backup policies, open security alerts, dependency manifests, and the last twelve months of incidents. Screenshots hide filters and expire the moment someone clicks away. Machine-readable exports can be compared, counted, and retained as closing evidence.

Use a reproducible first pass against every source-control organization the seller claims to use:

```bash
gh api --paginate '/orgs/ORG/repos?per_page=100' \
  --jq '.[] | [.full_name,.fork,.archived,.visibility,.default_branch,.pushed_at] | @tsv'
```

The output is one tab-separated row per repository. Compare the result with the service inventory, CI references, deployment manifests, developer account list, and domains used by production. Repositories that appear in only one source deserve inspection. So do services whose source appears nowhere.

Set evidence age limits. Current access and branch rules should come from the diligence window. A restore test from eighteen months ago proves only that an older system once restored. A dependency scan against a branch that is not deployed can be perfectly clean and completely irrelevant. Every artifact needs a collection time, collector, system of record, and scope.

Test completeness in both directions. Start with the ten customers that produce the most revenue and trace each to its tenant configuration, deployed version, custom code, support owner, and contract. Then select services from the cloud inventory without consulting the seller's architecture diagram and trace each back to source, owner, data, alerts, and customer impact. The first sample finds commercial exceptions. The second finds forgotten infrastructure. A diligence room organized only around management's service list cannot reveal an asset management does not remember.

Sequence requests so later answers cannot rewrite earlier facts. Collect inventories and access exports before architecture interviews, then ask engineers to explain anomalies without showing them one another's answers. Preserve the original exports and every corrected version. Corrections are normal in a complicated estate, but the change history tells the buyer whether the seller has learned something during diligence or is trying to make the evidence fit a prior claim.

Finding 1 is an evidence gap around a revenue-bearing service. Stop if the seller will not provide evidence or ownership cannot be established. Reprice when access is available and the missing map can be built with a defined discovery sprint, but price the interruption to the seller's team as well as the buyer's labor.

## Silent forks mean you may be buying the wrong code

A silent fork is any live line of code outside the declared authoritative repository: a developer fork with unmerged fixes, a customer branch used for production, a copied repository under another organization, or a deployment bundle edited after build. Buyers miss these because the main repository looks orderly. Production may be running something else.

GitHub's documentation explains that forks belong to a repository network and that visibility or ownership changes can alter what happens to that network. That model helps, but it does not settle acquisition ownership. A repository can be technically connected to the network while its account, contracts, commits, secrets, or deployment authority remain outside the assets being transferred. Treat network membership as a clue, not proof of title.

List remote branches and compare their divergence from the declared production branch:

```bash
git fetch --all --prune
git for-each-ref \
  --sort=-committerdate \
  --format='%(committerdate:iso8601) %(refname:short) %(objectname:short)' \
  refs/remotes/
git rev-list --left-right --count origin/main...origin/customer-x
```

The final command prints two numbers: commits unique to `origin/main`, then commits unique to `origin/customer-x`. A result such as `37 12` is not a verdict. It is a demand to identify the twelve commits, the environment running them, the customer promise behind them, and the person allowed to merge them.

Follow the build rather than trusting repository names. Take the version identifier from a running instance, trace it to an image digest or package checksum, trace that artifact to a CI run, and trace the run to an exact commit. If the chain ends at a laptop, a manually uploaded archive, or a deleted branch, the buyer cannot yet reproduce the product.

Finding 2 is a live fork or artifact that the seller cannot reconcile with the main line. Stop when code serving customers sits in an account excluded from the transaction, has unclear intellectual-property ownership, or contains changes nobody can reconstruct. Reprice when the fork is owned and readable but needs a planned merge, customer migration, regression testing, and a release freeze. Count all four tasks. "It is only twelve commits" says nothing about their behavioral difference.

## One maintainer can be a transfer blocker

Code concentration becomes an acquisition risk when one person combines knowledge, access, and execution authority for a critical service. Buyers often measure bus factor by commit count alone. That is too shallow. A prolific maintainer may have documented the system well, while a low-volume operations engineer may be the only person who knows which certificate renewal wakes up a legacy worker.

Run an author distribution, then test the result against operational ownership:

```bash
git shortlog -sne --all | head -20
git log --since='12 months ago' \
  --format='%aN <%aE>' | sort | uniq -c | sort -nr | head -20
```

These commands expose historical and recent contribution concentration. They do not reveal who reviews changes, owns vendor accounts, approves production access, understands the billing edge cases, or answers incidents. Interview the top maintainers separately and ask each to draw the same service path. Material disagreements show that the architecture exists in people, not in a shared operating record.

Finding 3 is a single-maintainer dependency on a revenue, identity, billing, data, or deployment path. It becomes a stop finding when that person will not transfer, the buyer cannot secure a transition agreement, or no second operator can complete a supervised release and recovery exercise before close. Reprice when the maintainer will transfer knowledge under enforceable terms and a second person can demonstrate the work. The remedy needs time in the purchase agreement, not a friendly promise in a meeting.

Finding 4 is hidden privilege concentration. Export human and machine identities from the identity provider, cloud, source control, CI, registrars, payment processor, certificate manager, observability service, and app stores if they apply. Map each privileged role to an employment or vendor agreement. Personal email addresses, shared accounts, recovery codes in a founder's phone, and service credentials billed to an employee's card all create transfer work.

Do not solve this by removing the person during diligence. Premature access changes can cause an outage and destroy evidence. First establish alternate control, rotate through an agreed runbook, record what changed, and test the affected workflows. Stop if control depends on an uncooperative third party or an account the seller has no contractual right to transfer. Reprice if the identity cleanup is finite and the seller completes it as a closing condition.

## The release path exposes who actually controls the product

A release is reproducible only when another authorized engineer can turn an identified commit into the same tested artifact and deploy it through recorded controls. A green CI badge is not enough. I have seen pipelines that compile on every commit while the real release requires a local environment file, a founder's approval in chat, and a manual database command copied from an old ticket.

Ask the seller to perform a no-op or low-risk production release with the designated successor operating the keyboard. The incumbent may observe but should not take over. Record the commit, workflow run, artifact digest, approvals, database changes, feature flags, health checks, and rollback decision. Then repeat in a nonproduction environment from a clean machine with newly issued credentials.

Treat secret delivery as part of the build, even though the secret values should not enter the data room. The buyer needs the secret names, owners, issuing systems, rotation procedure, environment scope, and proof that replacement credentials work. Look for values copied into CI variables by hand, long-lived tokens tied to personal accounts, and encryption material with no tested recovery path. Redaction protects the value; it must not hide the dependency.

Exercise the emergency path as well as the normal path. Find out who can bypass an approval, change a flag during an incident, disable a worker, or restore a previous artifact. Break-glass access needs an owner, a review trail, and credentials under transferred control. If the seller says nobody can bypass the process, verify that claim against administrator roles and cloud permissions. Most real systems have an emergency route. An unknown route is more dangerous than a documented one.

GitHub's protected-branch documentation describes controls such as required reviews, status checks, signed commits, and restricted pushes. Those controls reduce accidental and unauthorized changes, but configured rules are not the same as enforced practice. Inspect exceptions, administrator bypass, direct deployment permissions, stale reviewers, and whether the protected branch actually maps to production. A perfect rule on `main` is decoration if releases come from `release-old`.

Finding 5 is a laptop release or manual ceremony that cannot be repeated by a successor. Stop when the build inputs are unavailable, the artifact cannot be tied to transferred source, or rollback depends on a departing person. Reprice when the seller can document and automate the path, then prove it twice before close. One successful demonstration may be luck; the second shows that the process survived a reset.

Finding 6 is an untracked production mutation: shell edits on servers, console changes absent from infrastructure code, database procedures modified in place, or feature flags with no owner and no history. Compare declared infrastructure with cloud inventory and sample running configurations. Price the work to import, replace, or deliberately document every difference. Stop if investigators cannot determine what is running without disrupting customers.

Database migrations deserve their own demonstration because application rollback does not necessarily reverse data. Ask for the last schema changes that expanded, transformed, and removed data. Verify compatibility across the old and new application versions, the backup point before change, the observation window, and the procedure for a partial failure. A migration that succeeds on a small test database may lock a production table or leave old workers unable to read new rows. Price rehearsal time and temporary compatibility code, not just the minutes needed to run the statement.

## Customer forks turn product revenue into services debt

A customer-specific branch is not automatically bad, but an unpriced branch changes the economics of the acquisition. Each fork carries its own security patches, regression surface, release timing, and promise history. The buyer may think it is acquiring recurring software revenue while inheriting a small consulting business whose obligations sit in code and support messages.

Finding 7 is material behavior that exists only for one customer or cohort. Search branch names, feature flags, tenant identifiers, conditional billing logic, deployment manifests, and support tickets. Match every variation to a contract and to recognized revenue. If a custom path has no contract, the buyer cannot tell whether it is goodwill, a sales promise, or a feature the customer considers permanent.

Build a variation ledger with five fields: customer or cohort, code path, contractual obligation, annual revenue affected, and cost to merge or retire. Do not accept "we can move everyone to main later" without a compatibility test and a customer communication owner. Some forks exist because the main product cannot satisfy a regulatory, data-residency, or integration requirement. Removing them may remove the revenue too.

Reprice when the buyer can isolate the variations, estimate support load, and choose among merging, formal product tiers, or a paid end-of-life plan. Stop when the seller cannot identify which customers run which code, the branch contains unowned intellectual property, or a promised behavior conflicts with the buyer's operating or compliance model.

This finding often changes the multiple rather than only adding a cleanup budget. Revenue that requires separate engineering and release work does not have the same margin or scaling profile as revenue on the common product. Model it separately until the code and contracts prove otherwise.

## Dependency debt has legal and operational edges

Dependency age matters less than support, exploitability, replacement cost, and license obligations. A mature library with active maintenance can be safer than a recently published package controlled by one unknown account. The diligence question is whether the buyer can inventory what ships, establish the right to use it, and patch it on a commercially acceptable schedule.

Generate a software bill of materials from the deployed artifact or the exact source commit that produced it. CycloneDX and SPDX define machine-readable component formats; CISA's SBOM guidance calls for fields such as supplier, component name, version, identifiers, relationships, author, and timestamp. Those minimums are useful, but an acquisition needs more: deployment location, reachability, license review, replacement owner, and the customer versions affected.

Finding 8 is an unsupported or untraceable component on a sensitive path. Compare lockfiles and container layers with the SBOM, then sample components back to their manifests. Scan source history for vendored archives and copied snippets that package tools miss. Ask who receives vulnerability notices and how a fix travels to every supported customer version.

License ambiguity deserves separate treatment from a security alert. A vulnerable component may have a patchable technical remedy. Missing provenance or incompatible obligations can affect the seller's right to distribute the product at all. Stop when counsel cannot establish distribution rights for material code, source ownership is disputed, or a required source disclosure would contradict the deal model. Reprice support migrations and patch backlogs only after legal title is clear.

OpenSSF Scorecard examines repository practices including branch protection, dangerous workflows, dependency update tooling, maintained status, and token permissions. It is useful for triage across many repositories. It does not certify the product, inspect private operational behavior, or prove that the scanned repository produced production. Use the score to choose questions, never as the answer to diligence.

## Production must tell the same story as the architecture deck

Operational diligence should test whether the seller can detect failure, limit impact, and restore service with people and accounts that will transfer. Uptime claims without event definitions and source data are marketing statements. A dashboard can stay green while queued jobs fail, invoices duplicate, or one tenant reads another tenant's cached result.

Finding 9 is a recovery plan that has never restored the full service. Inspect backup success separately from restore evidence. Choose a representative database and attached object data, restore into an isolated account, apply secrets through the documented path, start the application, and run integrity checks. Record recovery start, usable-service time, data cutoff, manual interventions, and unresolved errors.

The test should expose hidden dependencies: DNS control, encryption keys, container registries, third-party callbacks, seed data, scheduled jobs, and account limits. A database restore alone does not prove recovery if the application cannot decrypt records or rebuild search indexes. Stop when backups are absent, unreadable, legally unusable, or controlled by an account outside the transaction. Reprice when recovery works but misses the contractual objective and the improvement plan has measurable work.

Finding 10 is an unverified tenant or data boundary. Trace authorization at the request, job, cache, export, support, analytics, and backup layers. Review how administrators assume customer identities and how the system logs that action. Sample negative tests that prove tenant A cannot read, update, export, or infer tenant B's data. A policy document cannot replace those tests.

This finding stops a deal when the product design cannot enforce material customer or regulatory promises, known cross-tenant exposure lacks a contained remedy, or the seller withholds incident evidence. It can support repricing when the defect is bounded, customers and counsel can be handled, and the buyer has a tested migration. Do not hide an uncertain incident inside a general technical-debt reserve. Treat it through security, legal, insurance, and deal terms together.

## Product economics can hide inside code and queues

Technical findings affect price only after they connect to cash, time, and retained revenue. Buyers weaken their position when they present a long issue list with no operating model. Sellers can dismiss that list as normal debt. Convert each finding into people, elapsed time, outside cost, downtime risk, and revenue at risk.

Model capacity, not only invoices. A remediation that consumes two senior engineers for eight weeks also delays the buyer's roadmap, integration work, and retention commitments. Give that displacement an owner and a business consequence. If the plan assumes hiring, include recruiting time, notice periods, onboarding, and the incumbent's remaining availability. A spreadsheet that starts work on the day after close with a fully staffed team understates the risk.

Run three cost views: the remedy if the seller cures the issue before close, the buyer's expected post-close work, and the downside if the first approach fails. Do not average them into one comfortable number. Link each view to observable triggers, such as a successful restore, signed intellectual-property assignment, merged customer branch, or successor-led deployment. Those triggers let the parties move price, holdback, or closing conditions when new evidence arrives instead of reopening the entire technical argument.

Finding 11 is a product margin that depends on invisible manual work. Inspect support queues, scheduled scripts, failed-job reprocessing, data corrections, invoice adjustments, onboarding tasks, and customer-specific reporting. Match the work to payroll and contractor records. If engineers manually repair the same workflow every week, the cost belongs to service delivery even if accounting places it in research and development.

Finding 12 is a contractual promise that the architecture cannot meet economically. Examples include retention periods without lifecycle controls, response commitments without on-call coverage, custom exports built by hand, or isolated deployments maintained as favors. Read a sample of large and unusual customer contracts beside the code variation ledger and incident history. The risk sits in the gap between promised behavior and repeatable operation.

Use a remediation register rather than a generic reserve. For each finding, record the action, accountable owner, dependencies, buyer and seller hours, external spend, earliest completion, service risk during change, and acceptance evidence. Add a contingency only where uncertainty remains and state what would retire it. This makes repricing discussable because each dollar connects to a transfer condition or a post-close workload.

Separate purchase-price adjustment from escrow, holdback, indemnity, and closing condition. Price addresses work the buyer knowingly inherits. Escrow or indemnity may address a defined contingent exposure. A closing condition forces the seller to produce evidence or complete a transfer before ownership changes. Using price alone for an untransferable repository does not make the repository appear.

## A stop finding needs an owner and a deadline

Diligence fails when serious findings remain adjectives in a report: "concerning," "immature," or "high risk." Give every finding a decision state. Use stop, reprice, cure before close, accept with named owner, or cleared by evidence. State who can change the state and the last date that still protects the transaction timetable.

The investment committee should see the twelve findings as claims with linked evidence, not a severity heat map. A stop claim names the missing right or capability, such as "Buyer cannot reproduce the production artifact from transferred source." Its clearance test is equally concrete: a successor builds, deploys, verifies, and rolls back an identified commit using transferred accounts and documented inputs.

I recommend arguing against the popular two-week cleanup promise. It is attractive because both sides preserve momentum and can label hard ownership questions as backlog. It is usually wrong when the missing evidence concerns source title, production control, tenant isolation, or restoration. Those issues determine what the buyer is acquiring. The seller should prove them while it still controls the people and systems needed to do so.

When the estate is large, a focused technical and operating audit can turn the uncertainty into costed decisions. The Team & AI Audit described on oleg.is is one way to identify engineering savings and operating gaps before a broader transformation, but the deal team still needs legal, security, financial, and commercial diligence around it. No technical reviewer can clear title or rewrite a customer contract by opinion.

Set the deadline before exclusivity runs out. If a silent fork remains outside the deal, a critical operator will not transfer, or the running product cannot be rebuilt and recovered, pause. If the seller produces ownership evidence and the remedy has a credible owner, schedule, acceptance test, and price, reprice. The discipline is not pessimism. It prevents the buyer from paying software margins for obligations that only heroic people can keep alive.
