Pre-launch bug finding. Fixed price.

Put it through the wringer before your customers do.

A fixed-price run through your whole product before launch, for teams with no QA of their own. Every bug that comes out is proved.

12Dashboardas shipped
11Undo paymentas shipped
10Spacesas shipped
09Debt namesas shipped
08Forecastas shipped
07Checkoutas shipped
06Promo ratesas shipped
05Two open tabsas shipped
04CSV importas shipped
03Debt scoreas shipped
02Backup, restoreas shipped
01Payment inputas shipped
UB-021DashboardA dated paid-off debt crashes the DashboardHigh
UB-015Undo paymentAn undone payment confirmation returns after navigationHigh
UB-029SpacesA payment draft leaks between spaces sharing a debt IDHigh
UB-023Debt namesA blank debt name crashes the validation messageHigh
UB-181ForecastA remaining cent is forecast as paid and displayed as zero or completeHigh
UB-009CheckoutWeb checkout fails before sending the plan requestHigh
UB-013Promo ratesAn expired promotional rate stays at the introductory rateHigh
UB-046Two open tabsA stale tab overwrites another tab's newly added debtHigh
UB-011CSV importTSV and quoted CSV imports corrupt debt fieldsHigh
UB-003Debt scoreA failed scoring request is shown as a successful zero scoreHigh
UB-004Backup, restoreBackup restore loses payment historyHigh
UB-006Payment inputDecimal comma payment input multiplies the amountHigh
In: as shippedScroll to run it
Out: proved00 of 192

That was 12. See all 192

We find the bugs your customers would have found. Then we prove every one.

Wringer goes through your product the way your users do and reproduces every finding before you see it. Each bug arrives with the exact steps, a measured screenshot and the line of code.

One engagement at a fixed price, from $5,000. No subscription. Nothing on this page is a mock-up: every exhibit links to its public record or to our own register.

192
bugs confirmed in one live app, each with proof
82
of them serious: wrong money, lost data, a crash or a blocked main flow
6 of 9
public reports fixed by a stranger's lead developer within 3 h 43 min

Who books this

Teams for whom a bug in production is an expensive day.

Your product moves money or holds customer records

A wrong balance, a payment applied twice, a restore that loses history. 82 of the 192 bugs in our own finance app were of that kind, and it had already shipped.

A launch or a large customer is weeks away

A public release, an enterprise pilot, an investor demo. Your developers test their own work and there is no QA team. You want an outside pass before the people who matter get theirs.

Much of the code was written by AI

One 2025 study of 470 pull requests found AI-co-authored changes carried about 1.7 times as many issues as human-only ones.4 You are shipping faster than anyone can check.

You are handing a build over

An agency delivering to a client, or a buyer looking hard at a product before a deal. You need a list of what is wrong, with proof, from someone who did not build it.

What this is not

  • A regression suite that runs on every commit. Subscription services do that well, and the table below shows what they cost.
  • A penetration test. We report security problems we come across, privately and first, but we do not attack your infrastructure.
  • Load or performance testing.

Exhibit A. Our own app, already live

192 confirmed bugs in one app. Here is every title.

Unburden is our own product, a debt payoff planner for web and Android that was already live. We ran the engine across it and kept a register: 192 distinct bugs confirmed, each with evidence. 82 are high severity, meaning a wrong financial result, lost or corrupted data, a crash, or a blocked main flow. A fix was written for each one, test first, and the fixes are going out in releases. The same bug on web and Android counts once.

We can print every title because the app is ours. A client's register is never published.

Showing 192
  1. UB-001MediumAmount displays omit the selected currency symbolAndroid + Web
  2. UB-002LowSettings shows the wrong app versionAndroid + Web
  3. UB-003HighA failed scoring request is shown as a successful zero scoreAndroid + Web
  4. UB-004HighBackup restore loses payment historyAndroid + Web
  5. UB-005HighBackup restore loses advanced settings and strategyAndroid + Web
  6. UB-006HighDecimal comma payment input multiplies the amountAndroid + Web
  7. UB-007HighKeeping a card open ignores ongoing spending in the rolloverAndroid + Web
  8. UB-008HighAn oversized payment exaggerates money paid and debt eliminatedAndroid + Web
  9. UB-009HighWeb checkout fails before sending the plan requestWeb
  10. UB-010MediumTrial copy says seven days instead of the approved fourteenAndroid + Web
  11. UB-011HighTSV and quoted CSV imports corrupt debt fieldsAndroid + Web
  12. UB-012HighMalformed backup metadata can corrupt startupAndroid + Web
  13. UB-013HighAn expired promotional rate stays at the introductory rateAndroid + Web
  14. UB-014HighOpening the score breakdown crashes the appWeb
  15. UB-015HighAn undone payment confirmation returns after navigationAndroid + Web
  16. UB-016HighOnboarding scores the extra amount as the whole payment budgetWeb
  17. UB-017MediumRestored onboarding inputs leave Calculate disabledWeb
  18. UB-018MediumOnboarding places the payoff date one month lateAndroid + Web
  19. UB-019MediumRecalculate stays enabled while a score request is pendingWeb
  20. UB-020HighA numeric debt ID reports a payment without changing the balanceAndroid + Web
  21. UB-021HighA dated paid-off debt crashes the DashboardAndroid + Web
  22. UB-022HighAn early rescore confirmation drops the arriving scoreWeb
  23. UB-023HighA blank debt name crashes the validation messageAndroid + Web
  24. UB-024MediumThe below-minimum budget warning is blankWeb
  25. UB-025HighThe supplied CSV template imports instructions as debtsWeb
  26. UB-026HighZero APR suppresses valid credit-card and loan calculator resultsAndroid + Web
  27. UB-027HighAn unpayable student plan is presented as a completed payoffAndroid + Web
  28. UB-028HighA zero consolidation term silently uses sixty monthsAndroid + Web
  29. UB-029HighA payment draft leaks between spaces sharing a debt IDWeb
  30. UB-030HighSecondary payoff calculators drop the freed minimum paymentAndroid + Web
  31. UB-031HighA paused payment month is replaced when calculating a boostAndroid + Web
  32. UB-032MediumDTI results show untranslated tier namesWeb
  33. UB-033HighBalance Transfer replaces a genuine zero APR with twenty-twoWeb
  34. UB-034MediumFeedback close controls have no accessible nameWeb
  35. UB-035MediumExported debt-free calendar dates disagree with the plan dateWeb
  36. UB-036HighDaily and annual interest summaries omit cash-advance ratesAndroid + Web
  37. UB-037HighThe minimum-payment split omits cash-advance interestAndroid + Web
  38. UB-038HighLifetime interest omits the cash-advance rateWeb
  39. UB-039MediumUnknown routes lose the app navigationWeb
  40. UB-040LowCoach setup shows literal HTML in the model-size textWeb
  41. UB-041HighDebt editing accepts values outside its declared numeric boundsAndroid + Web
  42. UB-042MediumSettings switches have no accessible namesWeb
  43. UB-043HighFocus advice and highlighting disagree with the payment planWeb
  44. UB-044HighThe trajectory starting balance already includes future interestWeb
  45. UB-045HighAvalanche priority ignores a scheduled post-promotion rateWeb
  46. UB-046HighA stale tab overwrites another tab's newly added debtWeb
  47. UB-047HighA payment can leave the cash-advance portion above the total balanceAndroid + Web
  48. UB-048MediumPaying the final debt bypasses the payment success revealWeb
  49. UB-049MediumCSV validation shows a raw translation keyWeb
  50. UB-050HighCSV import silently loses rows beyond its parser capWeb
  51. UB-051MediumDefault-space deletion offers a confirmation and silently does nothingAndroid + Web
  52. UB-052MediumThe deferred-interest warning displays the wrong calendar dayAndroid
  53. UB-053HighDeferred-interest risk is omitted from payoff priorityAndroid
  54. UB-054MediumThe debt-free countdown uses a different day from the planAndroid
  55. UB-055MediumOnboarding rejects a valid zero extra paymentWeb
  56. UB-056HighProjected scores ignore future debt balancesWeb
  57. UB-057HighFirst-run restore stages debts instead of restoring the full backupAndroid + Web
  58. UB-058MediumUpgrade feature explanations cannot be reached by keyboardAndroid + Web
  59. UB-059MediumPortuguese upgrade CTA omits price and trial durationAndroid + Web
  60. UB-060MediumStudent-loan time saving omits the numeric month countWeb
  61. UB-061LowEnglish consolidation description is a placeholderWeb
  62. UB-062MediumOnboarding annual savings badge disagrees with displayed pricesWeb
  63. UB-063MediumOnboarding lifetime price omits ninety-nine centsWeb
  64. UB-064MediumThe saved OTA draft is cleared during form initializationWeb
  65. UB-065HighOnboarding labels a fixed-payment baseline as the same minimum-payment saving as PlanWeb
  66. UB-066HighA pending voice payment can be retargeted to another spaceWeb
  67. UB-067MediumAn exhausted mounted Coach allowance stays exhausted in the next monthWeb
  68. UB-068MediumFree game replay uses a stale play count and permits a fourth startWeb
  69. UB-069HighRepeated Save events create duplicate debtsWeb
  70. UB-070HighPaid and archived debts incorrectly use the Free active-debt allowanceWeb
  71. UB-071HighQuick edit changes comma decimals and removes negative signsWeb
  72. UB-072MediumQuick edit shows a dollar prefix for another selected currencyWeb
  73. UB-073MediumQuick edit swaps Discard and Delete confirmation labelsWeb
  74. UB-074MediumFree installment entry silently applies the Pro-only payment estimateWeb
  75. UB-075HighA date-only maturity can shorten the estimate by one calendar monthWeb
  76. UB-076MediumSwitching installment types clears an unchanged estimate without recomputing itWeb
  77. UB-077MediumAn elapsed maturity is forced into a one-month estimateWeb
  78. UB-078MediumShared dialogs fall back to English action labels in PortugueseWeb
  79. UB-079HighCSV decimal commas silently change monetary amountsShared code
  80. UB-080MediumPending native entitlement changes spaces or shows the ended-plan gateShared code
  81. UB-081MediumA native store callback overrides an independently valid web entitlementShared code
  82. UB-082HighQueued Confirm All timers re-save already applied paymentsShared code
  83. UB-083MediumAccepted debt names make backups and CSV files unrestorableShared code
  84. UB-084LowBackup restore replaces a midnight reminder with 9 AMShared code
  85. UB-085MediumA hidden credit-card due day survives switching to a line of creditAndroid + Web
  86. UB-086HighClearing a monthly override saves zero instead of restoring the defaultAndroid + Web
  87. UB-087HighAddDebt rejects app-generated encrypted or larger valid backupsAndroid + Web
  88. UB-088MediumArchiving a debt emits a paid-off analytics eventAndroid + Web
  89. UB-089MediumA partial payment displays a paid-off check after subtracting twiceAndroid + Web
  90. UB-090MediumBusiness lines of credit cannot be selected in the charge simulatorAndroid + Web
  91. UB-091MediumDelete confirmation names the unsaved edit instead of the saved debtAndroid + Web
  92. UB-092HighSkipping a debt-type request changes the selected type to OtherAndroid + Web
  93. UB-093MediumPortuguese debt-form dates and actions remain EnglishAndroid + Web
  94. UB-094MediumAddDebt desktop and mobile summaries hardcode dollarsAndroid + Web
  95. UB-095LowPortuguese keep-open advice leaves most of its sentence in EnglishAndroid + Web
  96. UB-096MediumThe monthly budget editor always prefixes amounts with dollarsAndroid + Web
  97. UB-097MediumPortuguese annual saving badge omits its numeric percentageAndroid + Web
  98. UB-098LowPortuguese lifetime note is a placeholder instead of explanatory copyAndroid + Web
  99. UB-099LowMalformed JSON is explained as an unsupported file extensionAndroid + Web
  100. UB-100LowSettings CSV size refusal states 5 MB while the limit is 1 MBAndroid + Web
  101. UB-101HighA full payment history makes backup encryption overflow its argument stackAndroid + Web
  102. UB-102MediumBackup encryption failures leave Export without a visible errorAndroid + Web
  103. UB-103MediumCalendar Today selects the browsed month or year instead of todayAndroid
  104. UB-104MediumSwitching debt forms loses the page to return to after savingAndroid + Web
  105. UB-105MediumZero credit limit displays infinite utilizationAndroid + Web
  106. UB-106HighThe Plan quick-edit sheet is rendered in the wrong componentAndroid + Web
  107. UB-107HighAn unpaid 30-year calculator horizon is described as a strong payoff pathAndroid + Web
  108. UB-108HighGig Worker recommends a baseline above the available low-month surplusAndroid + Web
  109. UB-109MediumGig Worker describes zero surplus as an income gapAndroid + Web
  110. UB-110MediumGig Worker summary and buffer messages omit their numeric detailsAndroid + Web
  111. UB-111MediumBalance Transfer numeric inputs have no associated labelsAndroid + Web
  112. UB-112MediumThe returning Free empty Dashboard claims Pro features are readyAndroid + Web
  113. UB-113LowWhat-if debt prefills display more precision than AddDebt savesAndroid + Web
  114. UB-114MediumOnboarding offers Excel files but only parses delimited textAndroid + Web
  115. UB-115MediumExcluded-debt focus explanations show raw translation keysAndroid
  116. UB-116LowThe Burden Score trend stays English and prints a raw month keyAndroid + Web
  117. UB-117LowPortuguese space rename leaves its Save action in EnglishAndroid + Web
  118. UB-118HighBalance Transfer compares capped unpaid balances as lifetime costsAndroid + Web
  119. UB-119HighCredit-card projections mislabel incomplete and exact-cap resultsWeb
  120. UB-120HighConsolidation compares an unpaid baseline as a completed lifetime costAndroid + Web
  121. UB-121HighDTI retains an untouched debt-payment prefill after switching spacesAndroid + Web
  122. UB-122HighBudget keeps another space's untouched saved incomeAndroid + Web
  123. UB-123HighGig Worker presents capped interest as full-term interestAndroid + Web
  124. UB-124MediumDashboard clips over-limit utilization to one hundred percentAndroid + Web
  125. UB-125HighAccepted long debt names lose whole debts during backup restoreAndroid + Web
  126. UB-126MediumNative Back bypasses the pending-payment recalculation choicesAndroid
  127. UB-127HighWhatIf simulates negative APR and offers to save the scenarioAndroid + Web
  128. UB-128MediumEmbedded Plan scenarios return to the standalone WhatIf pageAndroid + Web
  129. UB-129MediumDashboard simulator shortcut targets a hidden Plan sectionAndroid + Web
  130. UB-130HighLoan calculator compares truncated horizons as complete lifetime resultsWeb
  131. UB-131HighDebt comparison silently omits positive debts with zero minimumsWeb
  132. UB-132HighDebt comparison calculates values outside its declared numeric boundsWeb
  133. UB-133MediumTwo-strategy calculator gives unsupported advice against MomentumWeb
  134. UB-134HighRefund calculator hides a completed boosted path when baseline is cappedWeb
  135. UB-135HighReturning to a saved scenario form overwrites a newer payment balanceAndroid + Web
  136. UB-136HighBNPL editing persists impossible or invalid installment countsAndroid + Web
  137. UB-137HighDebt comparison uses stale or rounded extra-budget prefillsAndroid + Web
  138. UB-138MediumDebt comparison fields lack accessible namesAndroid + Web
  139. UB-139LowCalculator catalog promises debt schedules that are absentAndroid + Web
  140. UB-140LowDebt comparison shows an explicit zero APR as blankAndroid + Web
  141. UB-141HighPlan rejects a budget that covers the actual final cycle minimumAndroid + Web
  142. UB-142HighPlan hides capped forecasts or describes them as lifetime Never and InfiniteAndroid + Web
  143. UB-143MediumUnchanged QuickEdit Enter submits and invents a payoff dateAndroid + Web
  144. UB-144MediumQuickEdit lacks Escape dismissal and dialog/input semanticsAndroid + Web
  145. UB-145LowDebt-free journey duration displays a unit without its numberAndroid + Web
  146. UB-146MediumManage Debts does not identify archived accountsAndroid + Web
  147. UB-147HighDebt-free celebrations include a global claim while archived debts remainAndroid + Web
  148. UB-148MediumFocus role button has no keyboard activation handlerAndroid + Web
  149. UB-149HighBiweekly annual boosts stop before the forecast horizonAndroid + Web
  150. UB-150HighBiweekly silently hides capped or missing-payment resultsAndroid + Web
  151. UB-151HighCleared zero-balance accounts inflate calculator payment budgetsAndroid + Web
  152. UB-152LowA zero unconfirmable payment row hides bulk UndoAndroid + Web
  153. UB-153MediumAn all-excluded Plan has an empty focus and misleading Extra labelAndroid + Web
  154. UB-154HighMonthly payment CSV headers also become recurring spendingAndroid + Web
  155. UB-155MediumSettings cannot retry the same selected invalid import fileAndroid + Web
  156. UB-156MediumSettings import controls cannot be activated by keyboardAndroid + Web
  157. UB-157HighA stale tab overwrites newly created spaces and makes their debts unreachableAndroid + Web
  158. UB-158HighA freedom-goal draft crosses spaces and overwrites the destination goalAndroid + Web
  159. UB-159MediumA negative freedom-goal budget is saved despite its declared zero minimumAndroid + Web
  160. UB-160MediumThe credit-card interest warning rounds away the payment threshold centsAndroid + Web
  161. UB-161HighFirst-run CSV drops declared debt types and recurring spendingAndroid + Web
  162. UB-162HighCredit-card calculator prefills an expired promotional APRAndroid + Web
  163. UB-163MediumCredit-card inputs and validation lack accessible names and error associationAndroid + Web
  164. UB-164MediumNegative extra payments hide Loan totals without explaining the invalid valueAndroid + Web
  165. UB-165MediumThe Loan interest warning rounds away its payment threshold centsShared code
  166. UB-166MediumStudent Loan compares invalid inputs or hides them without feedbackAndroid + Web
  167. UB-167MediumStudent Loan rounds a small aggressive-payment preset down to zeroAndroid + Web
  168. UB-168MediumOnboarding treats debt names as HTML and truncates quoted Remove labelsAndroid + Web
  169. UB-169MediumThe downgrade reset promises to delete settings and more accounts than its action removesAndroid + Web
  170. UB-170MediumA duplicate saved Plan layout renders duplicate calculator sectionsAndroid + Web
  171. UB-171MediumConcurrent image loads bypass the feedback form three-screenshot limitAndroid + Web
  172. UB-172MediumFeedback backup consent remains English in Portuguese and has an unnamed checkboxAndroid + Web
  173. UB-173MediumPlan persists negative or temporarily blank budget editsAndroid + Web
  174. UB-174MediumPlan has no explanation for only archived or zero-balance spending accountsAndroid + Web
  175. UB-175LowThe compressed timeline action promises to show all monthsAndroid + Web
  176. UB-176HighCSV spending fields make fixed loans grow while manual Save ignores the fieldAndroid + Web
  177. UB-177MediumInterest Flow shows infinite or negative percentages for unpaid interestAndroid + Web
  178. UB-178LowInterest Flow keeps its interest legend in English in PortugueseAndroid + Web
  179. UB-179MediumDebt editor numeric fields have no accessible namesAndroid + Web
  180. UB-180MediumThe secured-debt checkbox has no accessible nameAndroid + Web
  181. UB-181HighA remaining cent is forecast as paid and displayed as zero or completeAndroid + Web
  182. UB-182MediumAn unpaid Budget Dial preview displays a negative interest sentinel as moneyAndroid + Web
  183. UB-183MediumSelecting an unchanged score input requests another manual rescoreAndroid + Web
  184. UB-184MediumThe manual rescore action is skipped by normal keyboard navigationAndroid + Web
  185. UB-185MediumDashboard shows a debt-free date for a budget below required minimumsAndroid + Web
  186. UB-186MediumCreating a new active space leaves the screen in Combined viewAndroid + Web
  187. UB-187HighCombined view relabels and sums debts from different currencies as one unitAndroid + Web
  188. UB-188MediumAddDebt spreadsheet upload cannot be reached through normal keyboard navigationAndroid + Web
  189. UB-189MediumSettings subscription action cards have no keyboard semanticsAndroid + Web
  190. UB-190MediumThe selected subscription plan is not exposed programmaticallyAndroid + Web
  191. UB-191MediumUpgrade restore and gift-code fields have no accessible namesAndroid + Web
  192. UB-192LowPortuguese WhatIf controls retain English Reset and month suffixAndroid + Web

Register dated 5 November 2026. Titles are exactly as logged. Scroll the list, or filter it.

Exhibit B. Someone else's product

Then we ran it on a stranger's app. Its lead developer fixed six of nine the same night.

Our own app shows how much the engine finds. It cannot show that anyone else agrees. So we pointed the same engine at Traccar, an open-source GPS tracking platform with more than 8,000 stars on GitHub, using a local copy and never their servers. We filed nine reports on 6 November 2026. The six he fixed are in the log, in his own words.

Every line links to the public report. The reports carry the engine's internal codename in their footer.

  1. Nine reports filedAll nine inside three minutes.
  2. #2079 Positions keeps an old selected map after an empty reportHis fix: Clear selected position when reloading
    Fixed
  3. #2081 Exporting an empty device list fails without a workbookHis fix: Prevent exporting an empty device list
    Fixed
  4. #2078 Reloading a device or group Share page can crashHis fix: Fix share page crash while loading item
    Fixed
  5. #2074 An older Chart response can replace the latest device reportHis fix: Disable Chart report button while loading
    Fixed
  6. #2073 All Devices crosses into Chart as an invisible active valueHis fix: Exclude all from single-device reports
    Fixed
  7. #2076 Editing one calendar endpoint in another time zone can disable its recurrenceHis fix: Preserve calendar time zones when editing
    Fixed
Screenshot from report 2078: a share page replaced by a crash trace, boxed in red.
#2078 A page that crashes on reload. The red box marks the crash.
Screenshot from report 2079: a positions report still showing an old selected map after an empty result.
#2079 A report that shows nothing, with an old map left on screen.
Screenshot from report 2076: a calendar editor whose recurrence is disabled after editing one end in another time zone.
#2076 One edit in another time zone switches off a repeating schedule.

Why proof is the product

AI bug reports have a reputation. We know.

In January 2026 the curl project shut down its bug bounty after a flood of low-quality, AI-written reports. Its lead developer said the aim was to remove the incentive for people to submit crap and non-well researched reports.3

That is the bar. A report your engineers cannot reproduce costs more than it saves. So nothing leaves here until we have reproduced it ourselves, from a clean start, on your build. Leads that do not reproduce are dropped and listed as refuted, so you can see what we ruled out.

What you receive

One bug, as it lands in your tracker.

This is the text of a real public report, number 2073 in the log above. Every bug you get from us has the same parts, so an engineer can start on the fix without asking a single question.

Fixed

All Devices crosses into Chart as an invisible active value

Description

Opening Chart from a Summary report that uses All Devices leaves the Chart device field blank, but Show stays enabled and loads multiple devices into a single-device report.

Steps to reproduce

  1. Open Reports, then Summary.
  2. Select All Devices and press Show.
  3. Choose Chart from the report menu.
  4. Select Today and press Show.

Expected

Chart requires one visible selected device.

Current

The Device field is blank and Show is enabled. The response contained devices 1, 2, and 3.

Technical details

src/reports/components/ReportsMenu.jsx:35 through :39 carries the all value. ReportFilter.jsx:93 through :129 validates it as nonempty, then filters it out only when calling Show.

  • A title in the user's words. What breaks, not which function threw.
  • Steps anyone can follow. From a clean start, on your build. If the steps do not reproduce it, it is not in the report.
  • Expected against actual. Expected comes from your spec, your docs or the code's own intent, and we say which.
  • The line of code. File and line, so the fix starts in the right place.
  • A measured screenshot. The red box is drawn from the element's coordinates on the page, never by hand. A video of the bug happening is an add-on.
  • Severity by harm. High means wrong money, lost data, a crash or a blocked main flow. Low means it only looks wrong.
  • A retest. When you ship the fix we run the same steps again and close it, or tell you it is still there.

How an engagement runs

What happens after you say yes.

  1. Scope

    A 30-minute call. You choose the build and the journeys that must not fail. We sign your NDA before we see anything.

  2. Access

    Read access to the repository, a staging or test build, test accounts for each role, and whatever says how the product is meant to behave. We never need production data.

  3. The run

    Your build goes through the wringer. Your only job is to answer a short list of "is this intended?" questions. The delivery date is fixed on the scoping call.

  4. The register

    Every bug that held up, each with its proof, sorted by how much it would hurt your users.

  5. Walkthrough

    One call with your engineers. We go through the register and answer every question about it.

  6. Retest

    After your fixes ship, we run every bug's steps again and close what is fixed.

What the money buys elsewhere

You already buy one fixed-price test a year. This is the same purchase, for product bugs.

A penetration test is a one-off engagement with a scope, a report and a retest, and most teams have a budget line for it. A Wringer engagement has the same shape and sits in the same price range, pointed at the bugs your customers would hit instead of the holes an attacker would use.

OptionPublished costWhat you get
Pre-launch QA sprint from a testing shop$1,500 to $7,5005A set number of tester hours, screens and test cases, and a bug report at the end
Managed QA subscription$62,400 to $118,600 a year, median contract at three well-known vendors7Automated regression tests for the flows you specify, maintained for you
Hire a QA engineer$104,300 a year, US median wage6Ongoing testing, after hiring and ramp-up
Web application penetration test$5,000 to $50,000 per test8Security holes, with a report and a retest
Wringer engagementFrom $5,000, fixed before we startProduct bugs nobody listed in advance, each one proved, with a retest. Two thirds of the fee is due only on proof.

You can buy a week of manual testing for less. In the published QA offers we reviewed, none tied the fee to a number of proven bugs.

The engagement

One run. One fixed price, agreed before we start.

Products come in different sizes, so the price is set on the scoping call and does not move after it. Engagements start at $5,000.

What every run includes

  • A full read of your code and a pass through every screen in scope
  • Every finding reproduced in a browser, on iPhone or on Android before you see it
  • A register of confirmed bugs, each with steps, a measured screenshot, the file and line, and a severity
  • A short list of "is this intended?" questions, so your answer decides and not our guess
  • Replay scripts for confirmed web bugs, yours to keep and run
  • A walkthrough call with your engineers
  • One retest of your fixes within 30 days

What sets the price

  • The size of the product. Screens, features and user roles. A large product is done one area at a time, each as its own run.
  • The platforms. Web, iPhone and Android. One, two or all three.
  • How much you can tell us. Specs, tickets and known issues cut the back-and-forth.
  • Retests. One is included. More can be added.

Add-ons

  • The fix, handed over. A patch for each bug on a branch in your repository, with a test that fails before the fix and passes after. Your team reviews and merges.
  • Video of every bug being reproduced, start to finish.
  • Release cover. The same run again on your next release.
Get a fixed price

The proof rule

A bug counts only if it reproduces on your build from our steps.

You pay a third to start. The rest is due only if the run proves at least the number of bugs we agree on the scoping call, usually ten. If it falls short, you keep everything we found and owe nothing more.

Behaviour you tell us is intended does not count, and neither do duplicates.

Questions

What engineering leaders ask before they sign.

Do you need access to production or to customer data?

No. We work on a staging or test build, inside test accounts you create for us. If a flow involves money, we use the payment provider's test mode and never real money.

Will this bury my team in noise?

No. It might bury your team in bugs, though. We found 192 in our own app. Every one is reproduced before you see it, the same fault on two platforms counts once, and each carries a severity so you know where to start. What does not reproduce never reaches your tracker.

Will a long list make my team look bad?

No, and it is not a scorecard. Every product has these. Ours had 192 and it was already live. The register goes to you and nobody else, and a bug you found before a customer did is a credit to whoever ordered the run.

Do you fix what you find?

Your team fixes and we retest, unless you add the fix. With that add-on every bug arrives with a patch on a branch and a test that failed before it, for your engineers to review. We wrote one for every bug in our own register.

We already have automated tests. What does this add?

Tests check what someone thought to ask. This looks for what nobody asked: the stale tab that overwrites new data, the decimal comma that multiplies a payment, the restore that loses payment history. Those three are real entries in the register above.

Is this done by AI or by people?

Both. AI agents do the legwork, which is how one engagement can cover every screen. A person checks every report before it is sent, and that person is who you talk to.

What do you need from us?

Read access to your repository, a build we can run, test accounts, and about two hours of your time. Most of what we find starts with reading the code, so the repository is not optional. Beyond that, share whatever says what the product is meant to do: specs, tickets, designs, a list of known issues. One named engineer who can answer "is this intended?" during the run helps most of all.

What happens to our code and data afterwards?

We sign your NDA before we see anything. Your code and build are used for your engagement only and removed when the last retest is done.

What if you find a security problem?

You hear about it first and privately, outside the main report, the same day we confirm it.

How long before a launch should we book?

As soon as you have a build that runs. The delivery date is fixed on the scoping call, and you will want time to fix what comes out before the launch, not after.

Which platforms do you cover?

Web apps, iPhone apps and Android apps. The two exhibits on this page are web and Android only because that is what those two products ship.

Start here

Tell us what is shipping, and when.

A scoping call takes 30 minutes. You leave with a fixed price, a delivery date, and a plain answer on whether we are the right fit. If we are not, we say so on the call.

  • No subscription and no minimum term
  • NDA signed before we see anything
  • Two thirds of the fee is due only on proof

We use what you send to reply to you, and for nothing else. Privacy