The Paid Upstream Fix Playbook: Blocking Issue to Pinned Release
Turn one blocking upstream issue into a ranked list of 3-5 people who can land the fix, a merge-tied paid offer, and a dated tracker that ends in a pinned release.
Key takeaways
- Merge time barely differs between core-team and community pull requests (Cliff's delta -0.09) but correlates strongly with the contributor's track record on the project (rho -0.69), so pay for proximity to the affected code, not raw skill.
- A GitHub CODEOWNERS file blocks nothing unless required code-owner review is turned on, and any one listed owner's approval satisfies it, so check enforcement on a recent pull request before treating an owner as the merge authority.
- In Refolk's index, 124 US profiles and 47 German profiles carry "open source maintainer" in their headline, and 5 of the top 10 US employers in that set are large vendors, which makes the payment route a ranking criterion.
- A contractor whose code you take by assignment cannot truthfully sign a DCO or ICLA for it, so either you sign the project's CCLA or the statement of work carves the upstream patch out of the assignment.
- Open Source Collective keeps a fixed 10% host fee and pays only completed, invoiced work, so a contract routed through it is naturally pay-on-merge.
- The acceptance condition for a paid upstream fix must name a tagged release plus a fallback date, because a fix merged to main can sit unreleased for months.
This playbook is for engineering managers, technical founders, developer-relations leads and technical sourcers who have one open-source dependency blocking their work and the budget to get it fixed properly. It starts from a single blocking issue and produces three things: a ranked list of 3 to 5 people or firms with merge proximity to the affected code, a paid offer that is only accepted once the fix is merged upstream and in a tagged release, and a dated tracker. The file closes in one of two ways. Either you pin an upstream release, or you keep a deliberate local patch that someone owns and that has a written removal condition.
Whether to adopt, fork, replace or contain a stalled dependency is a separate decision. This guide starts after you have decided the fix belongs upstream.
What counts as done for a paid upstream fix?
A commissioned fix is done when it ships in a tagged upstream release, you have pinned that release, and you have deleted any local patch. The only other acceptable end state is a deliberate local patch with a named owner, a review date and a written removal condition.
"Merged to main" is not done. A fix can sit on the default branch for months before a tag ships. Pinning an untagged commit brings back the same maintenance you were paying to get rid of.
The case for pushing all the way to an upstream release, rather than keeping a private patch, is maintenance cost. The freedesktop.org packaging guidance describes a carried patch as work you repeat for every upstream release, because it has to be rewritten or forward-ported each time. The documented failure modes are specific:
- A patch to an upstream file conflicts whenever anyone else touches that file.
- A backport of a fix that is not yet upstream conflicts when upstream merges a different form of the fix.
- Consensus is slow. Purism's upstream-first guidance notes that it can take months for upstream to agree.
Nobody has published how many hours a forward-port takes per release, so do not quote a number to justify the spend. Estimate it locally instead. Count the upstream releases you expect to consume over the next year and the files your patch touches. Then count how often those files changed in the last year with git log --since=12.months --oneline -- <path> | wc -l. That last count tells you how many times your patch was exposed to a conflict.
Why merge proximity outranks skill
How fast a fix merges depends far more on the contributor's history with the project than on whether they are core team or how skilled they are. So pay the person reviewers already trust on the affected code, not the strongest engineer you can find.
Merge proximity means how close a person sits to the decision to merge changes on a specific path: whether they can merge it, own it, review it, or have recently written it. The evidence that it matters:
- Status barely matters. In the largest early study of pull-based development (Gousios et al., 291 projects), merged pull requests from the community and from the core team differed in merge time by a statistically significant but negligible amount (Cliff's delta -0.09). A pull request (PR) is a proposed change submitted for review and merge.
- Track record matters a lot. The same study found merge time strongly correlated with the contributor's track record on the project (rho = -0.69). The more prior PRs someone has landed, the faster their next one merges.
- Social distance matters. A later mixed-methods study of continuous integration found that contributors socially closer to a core team member had their PRs delivered more quickly.
- Requested reviewers raise the merge rate, not the speed. In nf-core, PRs with requested reviewers merged more often (95.70% vs 91.81%) but waited longer at the median (0.88 vs 0.30 days).
The mechanism is reviewer trust built up over many PRs. A skilled outsider pays that cost in full: slower review, more rounds and more requests to justify the approach. Paying someone with a track record on the path gets you that trust ready-made.
You are not buying code. You are buying a reviewer's existing trust in whoever writes it.
This evidence has two limits. First, no public source gives a median time-to-merge for first-time contributors against maintainer-authored PRs, or says how much a maintainer co-reviewing shortens it. Treat that as not established, and do not promise a figure internally. Second, the nf-core result means that even when you have paid for proximity, you still need to budget calendar time.
Proximity is one axis of the ranking. The other is whether you can actually pay the person. Put the two together and the call looks like this:
Ranking candidates for a paid upstream fix
Who can merge a fix: reading the evidence for a code path
The strongest evidence that someone can land a fix is write access plus recent merges on the affected path. After that, in order, come an enforced CODEOWNERS entry, recent review approvals on the path, and recent authorship. Only an enforced CODEOWNERS rule is binding. Everything else is inference.
CODEOWNERS is a file in a GitHub repository that maps path patterns to the people or teams who own them. MAINTAINERS and GOVERNANCE files are project conventions describing who holds which role, and the platform enforces neither.
How GitHub treats CODEOWNERS determines how you should read it:
- The file must be on the base branch for owners to receive review requests.
- The last matching pattern in the file applies, so read the whole file, not just the first match.
- Approval from any one listed owner satisfies the requirement.
- The file on its own blocks nothing. It is enforced only when an admin turns on required code-owner review.
- When enforcement is on, approval from a reviewer who is not in CODEOWNERS or who lacks effective Write permission does not unblock the merge.
To check enforcement without admin access, open a recent merged PR that touched your path and look for an automatic review request to the listed owner.
The commands
Run these from a fresh clone, scoped to the paths named in your issue:
git log --since=18.months -- <path>
git shortlog -sne -- <path>
git blame -w -C <file>
git blame -w -C --ignore-revs-file <revs-file> <file>
Then list the approvers on merged PRs that touched the path. Collapse duplicate author strings that belong to one person before you count anyone.
| Signal | What it proves | How it lies |
|---|---|---|
| Enforced CODEOWNERS entry | Their approval unblocks merges on the path | Rule is off, or owner lacks write access |
| MAINTAINERS or GOVERNANCE file | The project names them in a role | File is stale; person has moved on |
git blame on the hunks | Who last changed those lines | Names a reformatter or mass rename |
git shortlog -sne -- <path> | Who wrote most of the path | Top author has been inactive for a year |
| Approvers on merged PRs | Reviewers trusted on this path | Approver cannot merge without an owner |
Layers of merge proximity on a code path
- Write access with recent merges on the pathCan land the fix; the strongest proof
- Enforced code owner on the pathApproval unblocks the merge when required review is on
- Recent reviewer on the pathTrusted voice; may not hold merge rights
- Recent author on the pathKnows the code; still pays the trust cost in review
Nobody has published how often CODEOWNERS, blame and the people who actually review disagree. Assume they do disagree, and let a candidate's rank rest on at least two signals that agree.
How large is the pool of maintainers you can pay?
The pool is small, and much of it is employed. In Refolk's index of professional profiles, 124 US profiles and 47 German profiles carry "open source maintainer" in their headline, and 5 of the top 10 US employers in that set are large vendors.
| Metric | United States | Germany |
|---|---|---|
| Matching profiles | 124 | 47 |
| Ratio to Germany | 2.64x | 1.0x |
| Large vendors in top 10 employers | 5 | 4 |
| Freelance employer in top 10 | 0 | 1 ("Freiberuflich") |
| Top-region share of sample | Seattle and Redmond, 16% | Karlsruhe, 16% |
Source: Refolk's index, sample of 25 per query. The ratio and shares are derived.
| Metric | "open source maintainer" | "open source consultant" |
|---|---|---|
| US matching profiles | 124 | 142 |
| Founder, CEO or Co-Founder in top titles | 1 (Co-owner) | 6 |
| Foundation or project org in top employers | CNCF, AboutCode.org | TWiki.org, SUSE |
| Off-topic employers in top 10 | 0 | At least 1 (jewellery retailer) |
Source: Refolk's index. Counts are derived from the top-10 lists.
What these tables tell you:
- Employed maintainers are the norm. The top US employers include Okta, Dynatrace, Docker, Microsoft and AWS. The German list includes Datadog, NVIDIA, HubSpot and IBM. At employers like these, assignment clauses and CCLAs are likely to apply, so the payment route belongs in the ranking, not in a later admin step.
- Direct contracting looks more plausible in Germany. One of the top 10 German employers is a freelance entry. That is directional only, from a sample of 25.
- "Consultant" mostly surfaces firms. Founders and CEOs dominate the consultant results, which points to shops rather than individuals. The same query also returned a jewellery retailer, so a headline match proves nothing about proximity.
Firms are a real route, not just a fallback. Geomys, Filippo Valsorda's firm, runs on monthly retainers in which clients pay for sustainable maintenance of their dependencies and access to maintainer expertise. He started with six clients and earned the equivalent of his former Google total compensation. His publicly named clients include Tailscale, Teleport and Smallstep. Geomys associate maintainers include Nicola Murino (x/crypto/ssh) and Dominik Honnef (Staticcheck). If your dependency sits inside a firm like that, the firm may already hold the proximity you need.
Headline search is the wrong place to start. Path evidence is the right one. The friction is joining the two: you need to get from the names in your git shortlog to a current employer and to whether that person takes outside work. Refolk is built for that join. You ask in plain English for people with merge rights on a named repo who freelance, and you get back profiles matched across GitHub, LinkedIn and the open web. Then you check each one against your proximity map.
How do you pay them without breaking the contribution?
Choose the payment route before you scope, because the route sets the shape of the contract. Then make sure your IP clause leaves the contractor able to sign whatever the project requires: a DCO, ICLA or CCLA. Get either wrong and a finished patch cannot be merged, or cannot be paid.
The three payment routes
- Direct contract with the individual. This works when they are free to take side work and own what they write. Public rate anchors are thin. One maintainer, Colin Percival, stated $300/hour with discounts for open source in a forum post. Generic US IT consulting mostly falls in the $100 - $300 range. Nobody publishes fixed prices for upstream bug fixes, or "block of hours per year" retainer terms. Treat these as directional and re-check them before quoting.
- A firm or retainer. This works when a firm already employs or retains the maintainers of your dependency. A one-off fix can sometimes be scoped inside an existing retainer.
- The project's fiscal host. A fiscal host is an organisation that holds and pays out money on behalf of an open-source project. Open Source Collective charges a fixed 10% host fee on all incoming contributions. It cannot pay expenses in advance: invoices must be for completed work, and a project admin must approve them. It needs a W9 or W8 tax form once a payee's invoices reach $600 in a year, and its standard payment terms are 30 days. It can also register in a company's procurement system and accept purchase orders. These policies can change, so re-read the host's current expense policy before you scope.
A contract routed through a fiscal host is therefore pay-on-merge by default, which matches the acceptance condition this guide recommends. It does not fit an SOW that pays milestones up front. Decide which one you are writing before you send the offer.
The employment check
For every ranked candidate, record their employer and ask two separate questions:
- Does your employer allow paid side work?
- Who owns code you write outside work?
These are different issues. A moonlighting policy can get someone fired, but it does not transfer ownership of their work. The invention assignment clause does.
Statutes limit some of these claims. California Labor Code section 2870 voids invention assignment for work done on the employee's own time with their own resources, unless it relates to the employer's business or results from work for the employer. Section 2872 requires employers to give written notice of section 2870. Similar statutes exist in Delaware, Illinois, Minnesota and Washington. In the UK, employers own employee code by default, but the opposite is true for contractors. A fix to a project the employer itself depends on may fall under the "relates to the employer's business" exception, so do not rely on the statute without the candidate checking their own terms.
How common these restrictions are has not been established publicly. Ask; do not assume. If the answer is no, you still have three options: pay through the fiscal host, pay a firm, or have the employer sign the project's CCLA.
The licensing path
A DCO (Developer Certificate of Origin) is a per-commit Signed-off-by line certifying that the contributor has the right to submit the code. It grants nothing extra and relies on the project's existing inbound licence. The DCO was introduced in 2004 by OSDL for the Linux kernel. An ICLA (individual contributor licence agreement) covers code the individual owns. A CCLA (corporate contributor licence agreement) is signed by the employer or client, because code written within the scope of employment is usually a work made for hire owned by the company.
| Mechanism | Who signs | Patent grant | Paid contractor needs |
|---|---|---|---|
| DCO | Contributor, per commit | No | Right to submit the code |
| ICLA | Individual, once | Usually | To own the code |
| CCLA | Employer or client | Usually | Client signs if it owns the code |
The conflict hides in standard contractor clauses, which say the developer irrevocably assigns to the client all right, title and interest. Once the code is assigned to you, the contractor no longer owns it and cannot truthfully sign an ICLA or DCO on their own behalf.
The procedure: blocking issue to pinned release
The full run takes roughly 3 to 4 working days of your own effort, plus 1 to 2 weeks of calendar time for the employment check and about a week to contract. Upstream review time comes on top, and you do not control it. All time budgets here are desk estimates, because no published benchmark exists.
Blocking issue to pinned release
- Pin the defectWrite a minimal reproduction, name the failing version and the files or functions involved, and link or open the upstream issue. Done is a public issue with a repro and a path list, in 0.5 to 1 day.
- Map merge proximityRead CODEOWNERS on the default branch and the MAINTAINERS or GOVERNANCE file, then run path-scoped git log, shortlog and blame and collect approvers on merged PRs. Done is 5 to 10 names, each tagged write access, owner, recent author or recent reviewer, in about half a day.
- Rank 3 to 5 candidatesOrder by write access, then CODEOWNERS entry, then reviews on the path, then authorship, with an evidence link on every row. Done is a ranked list in about 2 hours.
- Confirm employment and payment routeRecord each candidate's employer and ask whether paid side work is allowed and who owns the code; if not, route through the fiscal host or a firm. Done is a confirmed payee and route, usually 1 to 2 weeks of calendar time.
- Scope and sign the SOWAgree the problem, approach, test and licensing path, carve the upstream patch out of IP assignment, and set acceptance as merged upstream and in a tagged release with a cap if review stalls. Done is a signed SOW in about a week.
- Carry an interim patch only if blockedApply a local patch whose header records the upstream PR, an owner, a review date and a removal condition. Done is a tracked patch, in about a day.
- Track review to releaseKeep a dated tracker of PR opened, first review, approval, merge and release tag, and act on the review date if it stalls. Done is a tagged release you can pin.
- Close the fileDelete the local patch, bump the pin and pay any final milestone. If the fix stalled, re-date the patch with a named owner and a removal condition instead.
The offer
Send this to your top-ranked candidate once you know their likely payment route. Hold the next candidate until you have a reply or a set number of days has passed.
Subject: Paid fix for <project> issue #<number>: <one-line defect> Hi <name>, I lead <team> at <company>. Issue #<number> in <project> is blocking us: <one sentence on impact>. The repro and the affected paths are in the issue: <link>. I am writing to you rather than opening a PR cold because of your reviews and commits on <path>. Proposed scope - Problem: <defect, failing version> - Approach: <outline, or "yours to propose in the issue first"> - Test: <regression test that must pass upstream> - Licensing: contributed under the project's <DCO / ICLA / CCLA> process. Our contract carves the upstream patch out of any IP assignment. Acceptance - Done when the fix is merged upstream and included in a tagged release. - If review stalls, payment for completed work is capped at <amount> on <date>, and you stay free to continue the work upstream. Payment - Fee: <hourly rate or fixed amount> - Route: direct invoice, your firm, or the project's fiscal host, whichever your employment terms allow. If paid side work is awkward under your employer's terms, which route would work for you? <name, role, contact>
Replace every angle-bracket field; keep the acceptance, cap and licensing lines intact.
The interim patch header
If you cannot wait for the release, carry the patch with a header modelled on Yocto's Upstream-Status tag. Yocto tags every patch with one of six status values, which lets a patch be audited without reading its diff.
Upstream-Status: <your status value> <upstream PR URL> Upstream-Issue: <issue URL> Owner: <name, team> Commissioned-From: <payee or firm, SOW reference> Added: <YYYY-MM-DD> Review-By: <YYYY-MM-DD> Remove-When: upstream release <tag> or later is pinned If-Stalled: <decision owner> decides keep, rework or drop on the Review-By date
Put this at the top of every carried patch file and put the Review-By date in the owner's calendar.
The tracker
Keep one row per commissioned fix, with a date in each of these columns: issue opened, offer sent, route confirmed, SOW signed, PR opened, first review, approval, merge, release tag, pin bumped, patch deleted. Every empty cell needs a next-action date.
Set the stall checkpoints from your project's own history. Measure the time from open to merge on recently merged PRs that touched your path. For a general reference only, the Gousios study found that 80% of merged PRs merged within 3.7 days, 90% within 10 and 95% within 26. Those figures cover PRs that did merge across a broad sample of projects. They are not a forecast for your fix.
How does a commissioned upstream fix go wrong?
Most failures are either a false belief about who holds authority or a break in the plumbing between the contract and the contribution. Each one below has a check you can run before it costs you money.
- CODEOWNERS treated as authority.
- Looks like: an owner listed in the file.
- Actually: the file is not enforced, or the owner has no write access.
- Check: read the file on the base branch, look for an automatic review request on a recent PR, and confirm the owner's own recent merges.
- Blame names the reformatter.
- Looks like: one person owns every line of the hunk.
- Actually: they ran a mass rename or lint commit.
- Check: rerun with
git blame -w -Cand an ignore-revs file, and confirm the person has reviewed other people's PRs on the path.
- The top author has left.
- Looks like: the highest commit count on the path.
- Actually: no activity in the last 12 months.
- Check:
git log --sinceshows recent work by that identity.
- The IP clause breaks the contribution.
- Looks like: a clean SOW and a ready patch.
- Actually: the SOW assigns the code to you, then the contractor signs a DCO or ICLA they cannot honour.
- Check: a CCLA is signed, or the SOW has a licence-back carve-out for the upstream patch.
- The payment route fails.
- Looks like: a signed SOW with a deposit milestone.
- Actually: the fiscal host will not pay in advance, so the first milestone never clears.
- Check: read the host's expense policy before scoping, and write host-routed SOWs as pay-on-completion.
- "Merged" is not "released".
- Looks like: success on the day of the merge.
- Actually: the fix lands on main, but no tag ships for months.
- Check: the acceptance condition names a release plus a fallback date.
- Orphaned interim patch.
- Looks like: a quiet, working build.
- Actually: the patch conflicts when upstream merges a different form, or silently reverts a fix.
- Check: every carried patch has an Upstream-Status-style header with an owner and a review date.
- Keyword noise in sourcing.
- Looks like: a long list of "open source consultants".
- Actually: headline matches include off-topic profiles. In Refolk's index, the consultant query returned a jewellery retailer.
- Check: every candidate must appear in the proximity map from commit, review or ownership evidence before they are ranked.
Two patterns show up across this list. Failures 1 to 3 and 8 are ranking errors, and you catch them by requiring two agreeing signals per candidate. Failures 4 to 7 are contract and tracking errors, and you catch them by writing the acceptance condition, the route and the patch header before any code exists.
Closing the file and keeping it current
Close the file only when the pin points at a tagged upstream release and the local patch is gone. If the fix stalled, close it only when an owner has re-dated the patch and written down its removal condition. Then keep the proximity map, because the next blocking issue in the same dependency will usually route to the same few people.
Before you close a commissioned fix
- The upstream issue has a minimal repro, the failing version and a path list.
- Every ranked candidate has an evidence link for write access, ownership, review or authorship on the affected path.
- CODEOWNERS enforcement was confirmed on a recent PR, not assumed from the file.
- Every ranked candidate has activity on the path within the last 12 months.
- The payee's position on paid side work and code ownership is recorded in writing.
- The SOW carves the upstream patch out of IP assignment, or a CCLA is signed.
- The acceptance condition names a tagged release and a fallback date with a payment cap.
- The payment schedule matches the route, with no up-front milestone on a fiscal-host route.
- Every interim patch carries an owner, a review date and a removal condition.
- The pin references a tagged upstream release and the local patch is deleted, or the patch has been re-dated by a named owner.
To keep the work current:
- Re-read the authority files on every new engagement. CODEOWNERS, MAINTAINERS and branch rules change, and an owner who could merge last year may not be able to now.
- Re-check money facts at the source. Fiscal host fees, advance-payment rules, tax thresholds and public rate anchors are all policies or one-off statements that can change. Read the current host documentation before scoping.
- Refresh the people side, not just the commits. Employers change faster than commit history shows. When the map is more than a few months old, re-run the same plain-English search in Refolk to confirm current employers and consulting status before you send an offer.
- Consider a retainer when fixes repeat. If the same dependency blocks you twice, the Geomys-style monthly retainer is the documented model for buying ongoing maintainer access rather than paying for one fix at a time.
Questions practitioners ask
How do I pay an open source maintainer to fix a bug?
Find the people with merge proximity to the affected code first, then ask each one which payment route their situation allows. The routes are a direct contract, a firm or retainer that employs maintainers, or the project's fiscal host such as Open Source Collective, which keeps a 10% fee and pays only completed work. Settle the route before you scope, because it decides whether you can pay milestones up front or only on completion.
Should a paid upstream fix be accepted on merge or on release?
Accept on release. A fix merged to the default branch can wait months for a tag, and you cannot pin it cleanly until one ships. Write the acceptance condition as merged upstream and included in a tagged release, then add a fallback date with a payment cap for completed work. That way a review stall does not leave the contractor unpaid or you holding an open-ended bill.
Can a maintainer employed by a large company take paid work on their own project?
Sometimes, and you have to ask rather than assume, because how common restrictions are is not publicly established. Ask two separate questions: whether their employer allows paid side work, and who owns the code they write. California Labor Code section 2870 and similar statutes limit employer claims to own-time work, but not work related to the employer's business. If the answer is no, route payment through a fiscal host, a firm, or a CCLA.
What should a statement of work for an open source bug fix include?
It needs six things: the problem with a link to a public repro, the approach, the regression test that must pass upstream, and the licensing path (DCO, ICLA or CCLA). It also needs an explicit carve-out of the upstream patch from any IP assignment clause, and an acceptance condition of merged upstream and included in a tagged release, with a dated cap if review stalls.
How long does it take to get a fix merged upstream?
There is no reliable public number for paid or first-time fixes. In one large early study, 80% of merged pull requests merged within 3.7 days and 95% within 26, but that covers PRs that did merge across many projects. Nobody publishes medians for first-time contributors against maintainers. Measure your own baseline from recent merged PRs on the affected path, and budget extra calendar time for review.
Is it better to upstream a fix or carry a local patch?
Upstream it, and carry a local patch only while the fix travels. A carried patch has to be forward-ported for every upstream release, conflicts whenever anyone else touches the same file, and breaks when upstream merges a different form of the fix. If you must carry one, give it a header naming the upstream PR, an owner, a review date and a removal condition.
Try it on the search you came here for
Stop building boolean strings. Just describe the person.
Type one sentence. I plan the search, read GitHub, public LinkedIn and Crunchbase records, and the open web as it is right now, and hand back a ranked list with the reason next to every name.
01Describe them
One plain sentence. Role, city, stack, stage, whatever matters to you.
02I read the web live
GitHub, public LinkedIn and Crunchbase records, the open web. Not a database that went stale last quarter.
03You read the shortlist
Ranked, with the reasoning under every name. Open a profile, ask a follow-up, narrow it down.
- Staff backend engineers in NYC who shipped Rust in production
- Series A fintechs in SF under 50 people, growing headcount this year
- Maintainers of fast-growing Rust web frameworks on GitHub
- No boolean, no filters, no seat to buy. One box.
- Read at search time, so a profile updated yesterday counts today.
- Every step visible as it runs, every name with its reason.
500 free credits on sign-up. No card, no demo call. See real searches.