Dev Agency Handover: 5 Technical Checks Before Releasing Final Payout

Never release final escrow payments based on a screen-share demo. Learn the 5 technical audit checks required to verify codebase health and avoid costly rewrites.

MG
Mehdi Golzari
Senior Independent Technical Partner
September 11, 2026· 10 min read
Dev Agency Handover: 5 Technical Checks Before Releasing Final Payout

Dev Agency Handover: 5 Technical Checks Before Releasing Final Payout

Non-technical founders face a recurring, expensive crisis: your software development agency delivers a polished Zoom screen-share demo, asks for final milestone sign-off, and receives the remaining 30% of your development budget. Two months later, when you try to onboard an in-house engineer or present your architecture to seed investors, you discover the application cannot run on a local machine without undocumented manual patches, hardcoded API secrets litter the Git commit history, and the database contains zero referential integrity.

Releasing final escrow payments based on a superficial UI walkthrough is the single fastest way to inherit toxic technical debt.

Before releasing the final payment, run this 5-step technical handover audit. It validates that you own a secure, deployable, and investor-ready asset, rather than an unmaintainable prototype that requires a total rewrite.

The Anatomy of a Flawed Agency Handover

#

Software agencies operate on throughput and margin. Once an agency delivers visual functionality matching your specification, their financial incentive is to close the contract as fast as possible. Consequently, standard engineering rigor—such as deterministic database migrations, automated test harnesses, and infrastructure-as-code—is routinely compromised.

When you review agency code without automated verification, you are reviewing a facade. Beneath that slick frontend often lies a fragile ecosystem:

CODE
+-------------------------------------------------------------------------+
|                        AGENCY HANDOVER AUDIT FLOW                       |
+-------------------------------------------------------------------------+
|                                                                         |
|  [Agency Deliverable]                                                   |
|          │                                                              |
|          ▼                                                              |
|  [Check 1: Clean-Room Build] ────► Fails? ──► REJECT: Unrunnable Repo   |
|          │ Passes                                                       |
|          ▼                                                              |
|  [Check 2: Secret & Security Scan] ─► Fails? ──► REJECT: Leaked Keys    |
|          │ Passes                                                       |
|          ▼                                                              |
|  [Check 3: DB Schema & Migration] ──► Fails? ──► REJECT: Corrupt State  |
|          │ Passes                                                       |
|          ▼                                                              |
|  [Check 4: Infrastructure & IAM] ───► Fails? ──► REJECT: Vendor Lock-in |
|          │ Passes                                                       |
|          ▼                                                              |
|  [Check 5: Strict Type & Test Evals]► Fails? ──► REJECT: Blind Regress  |
|          │ Passes                                                       |
|          ▼                                                              |
|  [FINAL MILESTONE ESCROW RELEASE APPROVED]                              |
+-------------------------------------------------------------------------+

Before wiring the final balance, perform technical due diligence on the five failure surfaces detailed below.

Check 1: The Clean-Room Local Cold Start

#

A production codebase must build deterministically from scratch without relying on lingering dependencies on an agency developer's laptop. If an engineer cannot clone the repository onto a clean machine, execute a single command, and have a fully functioning local environment with seed data running within 15 minutes, your handover fails.

Important Architectural Requirement

[!IMPORTANT] Never accept an agency handover where configuration instructions reside inside a Slack thread or rely on "we will jump on a call to set it up." All environment setup must be declared deterministically in a tracked docker-compose.yml and accompanied by a comprehensive .env.example file.

Verification Procedure

#
  1. Spin up an isolated local environment (or a fresh VM).
  2. Clone the repository without any pre-existing global dependencies except Docker and Node/Python/Go.
  3. Execute the automated bootstrap script.
BASH
#!/usr/bin/env bash
# handover-verification.sh: Execute a clean-room cold-start test

set -euo pipefail

echo "=== [STEP 1] Validating Environment Templates ==="
if [ ! -f ".env.example" ]; then
  echo "ERROR: .env.example is missing from repository root."
  exit 1
fi

# Ensure no production secrets exist in example file
if grep -E '(sk_live|AKIA[0-9A-Z]{16}|ghp_)' .env.example; then
  echo "CRITICAL SECURITY FAILURE: Live API credentials found in .env.example!"
  exit 1
fi

cp .env.example .env.test

echo "=== [STEP 2] Launching Containerized Infrastructure ==="
docker compose -f docker-compose.test.yml down -v
docker compose -f docker-compose.test.yml up --build -d

echo "=== [STEP 3] Running Automated Migrations & Seeds ==="
docker compose -f docker-compose.test.yml exec -T api npm run db:migrate:deploy
docker compose -f docker-compose.test.yml exec -T api npm run db:seed

echo "=== [STEP 4] Executing Health Probe ==="
STATUS=$(curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/health || true)

if [ "$STATUS" -ne 200 ]; then
  echo "HANDOVER FAILURE: Health endpoint returned HTTP status $STATUS (Expected 200)"
  exit 1
fi

echo "SUCCESS: Clean-room bootstrap succeeded deterministically."

If this script fails at any point, withhold the final milestone. To avoid these traps before writing a single line of code, review our Founder-to-Launch Blueprint™ to establish enforceable engineering boundaries early.

Check 2: Secret Leaks and Git History Sanitization

#

Agencies frequently hardcode API keys, production database credentials, and third-party SaaS tokens into code during early development, only removing them from the active branch right before delivery.

However, Git maintains complete historical memory. If an agency developer committed an OpenAI secret key or AWS access token on commit 3b9f1a, anyone with read access to the repo can extract that token, even if it does not appear in the latest files.

Common Founder Pitfall

[!WARNING] If an agency commits live credentials to Git and pushes to a shared or public repository, bots index those keys in seconds. You are exposed to catastrophic API bills or database ransomware before you even launch.

Run an automated scanner across the entire repository history before accepting transfer:

BASH
# Run Gitleaks across the complete commit history
docker run -v "$(pwd):/path" zricethezav/gitleaks:latest detect \
  --source="/path" \
  --verbose \
  --redact

If exposed credentials exist in the history, the agency must:

  1. Revoke and rotate every single compromised key in the relevant cloud provider dashboard.
  2. Scrub the Git history using git-filter-repo or BFG Repo-Cleaner.
  3. Verify that zero secret values are committed to .env.example or staging configs.

Check 3: Database Schema Integrity and Migration Rollbacks

#

Many agency MVPs contain messy schemas without foreign key constraints, missing compound indexes on critical lookup queries, or using raw SQL scripts executed directly in production without tracked migrations.

When audit teams evaluate applications for investors, broken data layers are a primary red flag. For a detailed breakdown of how these issues derail fundraising, read Why Offshore Agency Codebases Fail Seed Due Diligence.

SQL
-- ANTI-PATTERN: Brittle, unconstrained table structure often seen in agency deliverables
CREATE TABLE tenant_invoices (
  id UUID PRIMARY KEY,
  tenant_id TEXT, -- No foreign key constraint! Risk of orphaned records
  amount NUMERIC, -- No NOT NULL constraint, allows corrupted states
  created_at TIMESTAMP -- Unindexed column on a table filtered constantly by date
);

-- PRODUCTION-GRADE PATTERN: Strict constraints, explicit relations, and indexing
CREATE TABLE tenant_invoices (
  id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
  tenant_id UUID NOT NULL REFERENCES organizations(id) ON DELETE RESTRICT,
  amount_cents INTEGER NOT NULL CHECK (amount_cents >= 0),
  currency VARCHAR(3) NOT NULL DEFAULT 'USD',
  status VARCHAR(32) NOT NULL DEFAULT 'pending',
  created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
  updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

-- Compound index for fast tenant-scoped billing queries
CREATE INDEX idx_tenant_invoices_tenant_status_created 
ON tenant_invoices (tenant_id, status, created_at DESC);

If you run a multi-tenant B2B SaaS, verify that the database enforces tenant isolation at the schema or query layer. Review our guide on Postgres RLS: Multi-Tenant Architecture for SaaS MVPs to audit whether your agency correctly implemented isolation or left you open to cross-tenant data leaks.

The Migration Rollback Test

#

Require the agency to demonstrate bi-directional migrations. Run the following check in your local test environment:

BASH
# 1. Apply all forward migrations
npm run db:migrate:up

# 2. Roll back the last 3 migrations
npm run db:migrate:down 3

# 3. Re-apply migrations to ensure idempotency
npm run db:migrate:up

If a migration cannot be rolled back cleanly without throwing an unhandled database error, your application cannot safely deploy continuous updates.

Check 4: Infrastructure Ownership and IAM Offboarding

#

Never accept an application hosted on an agency's personal AWS, GCP, Vercel, or Supabase accounts. You must retain absolute, root-level administrative ownership of all digital assets.

Architectural Context

[!NOTE] A software escrow checklist must document that DNS records, domain registrars, payment processor webhook endpoints (e.g., Stripe, Lemon Squeezy), and transactional email domains (e.g., Resend, Postmark) are registered directly under corporate accounts owned by your entity.

Infrastructure Handover Matrix

#
Asset LayerAgency Deliverable ExpectationCritical Verification Check
Source ControlGitHub/GitLab Organization transferVerify Founder is Organization Owner; remove agency admin rights; enforce 2FA.
Cloud ProviderAWS/GCP/Azure Root AccountBilling linked to founder credit card; agency downgraded to temporary IAM role.
DatabaseManaged instance (RDS/Supabase/Neon)Master password reset; automated daily snapshot backups enabled.
CI/CD PipelinesGitHub Actions / CircleCIAll deployment workflows execute via automated runner without manual steps.
Third-Party APIsStripe, OpenAI, Resend, SentryAll API keys regenerated; webhook signatures pointing to production URLs.

If your architecture uses overcomplicated multi-cloud infrastructure or microservices built prematurely by an agency to inflate billable hours, read our analysis on The MVP Microservices Trap: Why Early-Stage SaaS Needs a Modular Monolith.

Check 5: Strict Type Safety & Automated Test Integrity

#

Agencies often bypass TypeScript checks using // @ts-ignore or any across frontend and backend boundaries to hit milestone deadlines.

TYPESCRIPT
// ANTI-PATTERN: The "Agency Shortcut" that hides runtime crashes
export async function processPayment(payload: any): Promise<any> {
  // @ts-ignore
  const result = await stripe.charges.create({
    amount: payload.amt,
    currency: payload.curr,
    customer: payload.user.stripe_id,
  });
  return result;
}

// PRODUCTION-GRADE: Strict interface definition with runtime boundary parsing
import { z } from 'zod';

export const PaymentPayloadSchema = z.object({
  amountCents: z.number().int().positive(),
  currency: z.enum(['USD', 'EUR', 'GBP']),
  customerId: z.string().startsWith('cus_'),
});

export type PaymentPayload = z.infer<typeof PaymentPayloadSchema>;

export async function processPayment(payload: PaymentPayload): Promise<PaymentResult> {
  const validated = PaymentPayloadSchema.parse(payload);
  return await paymentGateway.charge({
    amount: validated.amountCents,
    currency: validated.currency,
    customer: validated.customerId,
  });
}

Run the Zero-Warning Build Check

#

Execute these two commands from the root directory:

BASH
# 1. Strict TypeScript compilation check
npx tsc --noEmit --strict

# 2. Automated test suite check
npm run test:ci

If tsc returns hundreds of type errors or the test suite contains zero assertions (or simply tests trivial helper functions while skipping business-critical database transactions), refuse the milestone approval.

Handover Verification Approaches: A Comparison

#
ApproachTime-to-AuditFinancial RiskDev ComplexityFailure Risk
Superficial Demo Review1 HourHigh (100% liability on founder)LowCritical (80%+ rework rate)
Scripted Developer Audit1 - 2 DaysModerateMediumLow-Medium
Fractional CTO Due Diligence3 - 5 DaysNegligible (Protected Capital)High (Senior-Level)Negligible (Investor-Ready)
Founder Recommendation

[!RECOMMENDATION] If you lack the in-house engineering background to execute these verification scripts yourself, engage a Technical Due Diligence & Codebase Audit before releasing your final escrow milestone. Identifying structural flaws while the agency is under contract saves tens of thousands of dollars in emergency engineering fixes later.

The Founder's 5-Step Handover Action Checklist

#
  1. Withhold 20% to 30% Milestone Retention: Never structure an agency contract where 100% of the funds are dispersed immediately upon UI delivery. Always mandate a 14-day technical verification soak period.
  2. Transfer Git Organization Ownership First: Require the agency to transfer administrative ownership of the GitHub/GitLab organization to your corporate account before auditing the code.
  3. Run Independent Local Builds: Execute the clean-room cold-start script on a machine that has never interfaced with the agency's developers.
  4. Rotate and Revoke Every Credential: Invalidate all temporary agency IAM users, rotate database master credentials, and regenerate every API key across all third-party services.
  5. Secure an Independent Engineering Assessment: If you are planning an institutional funding round or preparing for heavy customer acquisition, consider partnering with an experienced Fractional CTO Advisory to ensure your codebase is structurally sound, scalable, and ready for market.
Founder-to-Launch Framework™

Want to stress-test your SaaS MVP architecture?

Avoid premature technical debt and validate your product boundaries before writing code. Build your customized Go-to-Launch Blueprint™ free in under 10 minutes.

MG

Written by Mehdi Golzari

Independent Technical Partner & Senior Architect helping early-stage SaaS and AI founders take products from ideation to scalable production without agency overhead.

Related Technical Articles

View all articles →