Skip to content
  • USVC
  • Meridian
  • Nova
Sign inContact sales
Blog

Category

Engineering

Written by

Thibaut Labarre
Thibaut Labarre
Engineering Lead
Copied link
Blog
Engineering

A PR a Day Keeps Tech Debt at Bay

We deleted 12,000 lines of code this summer, with small PRs landing every weekday morning, written by an AI agent working from a short written recipe.

Oct 29, 2026 — 5 min read

Workflow diagram with a card backlog, three completed cards, a current card, future cards, and a crane adding a new card.A task progress visualization showing completed cards for Monday, Tuesday, Wednesday; a highlighted current card for Thursday with a blue block above it; and a pending card for Friday.

Written by

Thibaut Labarre
Thibaut Labarre
Engineering Lead
Copied link

The migration graveyard

Every engineering team has a migration graveyard. Nobody can justify a sprint on it, so it happens nights and weekends, sporadically, then stops.

In September we finished two big ones:

  • Faraday (backend). All six of our Ruby services now make outbound web requests through one library, Faraday, instead of three.
  • Apollo (frontend). Our fundraising app now loads data one way instead of two: hooks instead of the older "render prop" style.

It started with a pull request (PR) or two each weekday, opened without anyone asking, each converting a single page. As we came to trust our AI coding agent, we let it open more and fold several pages into each one: about eight a day by September, until the last Apollo code was gone. That is how 395 places fit into 202 Apollo PRs. Faraday went the other way. Its 32 places took 41 PRs, because several turned into deletions that reached across services. An engineer reviewed each change, and we reverted one. Along the way, the migrations removed about 12,000 lines of hand-written code on net.

Review never turned into a rubber stamp. The pages got harder as we went, about 900 lines per PR by mid-September against 270 in August. Even as the pace quadrupled, the share of PRs that drew a reviewer comment rose from 15% to 45%. All of it fit in a 30-minute review block each day, under four minutes per PR at the September pace.

FaradayApollo
Change

HTTParty and Net::HTTP to Faraday

Render-prop wrappers to hooks

One pull request covers

One service, or a deletion across several

One page at first, several by September

Places to change

32

395

Pull requests, estimated / actual

10 / 41

58 / 202

How the migration happened

worked from least to most risky: standalone services, then shared libraries, then the shared request layer everything depended on

mechanical rewrite with one example pull request to copy, plus rules that began as review comments

The playbook

Every migration we take on is tracked like a normal project: owner, estimated and merged pull requests, percent complete, incidents caused, and a playbook. The playbook is a written recipe for exactly one unit of work, small enough for one pull request. A recipe like this works for a new engineer. It also works for a coding agent, every morning, without being asked.

The first Faraday PRs carefully ported code that nothing called anymore. So we taught the recipe to check first, and 6 of the 41 Faraday PRs became deletions. Here's the step:

Confirm the integration is still live in production before migrating it. Several of these call sites are long-dead legacy code, and migrating them wastes review time. Dead code should be deleted, not ported. Check all three signals:

  • Traces: search Datadog for calls to the vendor's hostname over at least 90 days. Zero calls is the strongest signal.
  • Data: count the records the integration writes, and check when the last one was written.
  • Reachability: trace the call site back to a live entry point (a controller, a worker schedule, a cron job).

Then decide. Live: migrate it. Dead: open a deletion PR instead. Ambiguous: migrate it and note the uncertainty in the PR.

One pull request per run

Each migration has a scheduled coding agent session that runs every weekday. Its instructions center on one line:

EVERY RUN MUST OPEN ONE NEW PR. That is the deliverable.

We never changed that line. To speed up Apollo, we scheduled more runs each day and let each unit cover several pages.

The rest protects that line:

  • Fix yesterday's work first, quickly. Failing tests and unanswered comments get fixed. A pull request waiting on a reviewer never blocks today's.
  • Look at the code, not the notes. The next unit comes from searching the code as it stands, and the run checks open pull requests so it never collides with work in flight.
  • One pull request, one message. When tests pass, it posts a review request in our code review channel with a progress bar counted fresh from the code, and updates Linear to match.
  • Never go quiet. If it can't open a pull request, it says so and tags an engineer.
  • Stay on budget. If a unit won't fit its spending limit, it asks an engineer instead of grinding.

The day it broke a page

One day, an Apollo conversion crashed a specific page for every user. The old code read account details only when a pop-up actually opened. The conversion moved those reads into the form's starting values, which run as soon as the page loads, so they ran with the pop-up closed and the account not yet loaded. An engineer reverted it immediately, we fixed the root cause, and the playbook gained five new rules. The simplest: test the page with the pop-up closed. One bad pull request broke one page, took one revert to undo, and made the recipe better for every run after it.

What we learned

  • Start small, then grow the unit as trust grows. One service or one page per pull request kept early reviews quick, mistakes contained, and reverts easy. Once the reviews ran clean, we let each pull request cover more.
  • Estimates will be wrong, and that's fine. Both migrations took three to four times as many pull requests as we planned. A daily habit doesn't care how many days it takes.
  • Reuse the recipe. We're now using the same recipe to run other daily migration jobs, from replacing admin pop-ups with proper dialogs to speeding up the slowest production endpoint each morning.

On September 21, the Apollo job found nothing left to convert and posted, unprompted:

No candidates left for this automation. Suggest retiring it or repointing it at a new target.


Latest articles

Data

The Impossibility of “Indexing” Seed

Sep 18, 2026 — 12 min read
Data

Fund Benchmarks: A Mid-Year 2026 Refresh

Sep 4, 2026 — 4 min read
Engineering

The Semantic Layer Nobody Maintains

Aug 28, 2026 — 19 min read

Give everyone a stake in the future of technology

Contact salesSign in

Funds

Solutions

  • Established Firms
  • Emerging Managers
  • Fund Migrations

Agentic Fund Management

  • AngelList LinkNEW

Products

Fund Administration

  • Venture Funds
  • Rolling Funds
  • Scout Funds
  • SPVs
  • Roll Up Vehicles

Investor Management

  • Digital Subscriptions
  • Data Room

Resources

Company

  • About Us
  • Careers

Explore

  • Blog
  • Help Center
  • Education Center
  • Data Center

Calculators

  • VC Fund Performance Calculator
  • RUV Calculator

By AngelList

  • USVC
  • Meridian
  • Rollups
© AL Advisors Management Inc.TermsPrivacyDisclosures

Looking for AngelList Talent? WellFound is no longer a part of the AngelList portfolio.

Disclaimer:

The information contained herein is provided for informational and discussion purposes only and is not intended to be a recommendation for any investment, service, product, or other advice of any kind, and shall not constitute or imply an offer of any kind. Any investment opportunities and/or products or services shown here will only be completed pursuant to formal offering materials, a letter of intent, and/or any other agreements as determined by AngelList containing full details regarding risks, minimum investment, fees, and expenses of such transaction. Any examples are provided for illustrative purposes only and do not constitute a guarantee or prediction of any particular investment outcome. Investing in funds is inherently risky and illiquid, and comes with the risk of losing all or a substantial portion of an investment. Any references on this website to USVC are provided for informational purposes only. USVC is a separate investment product from AngelList’s platform products and services. USVC is a registered closed-end fund managed by AngelList Asset Management LLC (“AAM”), an SEC-registered investment adviser that operates independently from AngelList’s platform businesses. Nothing on this website constitutes an offer to sell, or a solicitation of an offer to buy, shares of USVC; shares of USVC are offered only by prospectus, which contains important information about the fund’s investment objectives, risks, charges, and expenses and is available at usvc.com. The terms of any product, service, or particular investment opportunity, including size, costs, and other characteristics, are set forth in the applicable constituent documents for such product, service or particular investment opportunity and may differ materially from those presented in this presentation. Such terms are subject to change without notice. For more information on AngelList and its products and services, please see here.

Quotes included in these materials related to AngelList's services should not be construed in any way as an endorsement of AngelList's advice, analysis, or other service rendered to its clients.