Skip to main content
Find bank-fee leakage in a week: a fee-mapping checklist, SQL reconciliation examples and a vendor-negotiation script for small businesses

Find bank-fee leakage in a week: a fee-mapping checklist, SQL reconciliation examples and a vendor-negotiation script for small businesses

A tight, five-day plan to find money your bank is quietly taking and actually claw some of it back

Most SMBs never look at their bank fees line by line. The charges show up buried in the statement, coded with cryptic descriptors like "ACCT ANALYSIS FEE" or "MERCHANT SVC 0042," and nobody has time to figure out whether a $38 charge is legitimate or a slow leak that's been running for three years. That's exactly why it keeps happening.

The thing is, bank fee optimization for a small business isn't hard. It doesn't require a treasury consultant or a fancy cash-management system. It requires about a week of focused work, a clean export of your transactions, and the willingness to ask your banker uncomfortable questions. This post walks through the actual steps — the fee-mapping table, the reconciliation queries, the thresholds that tell you when to act, how sweep accounts really work, and a word-for-word script for the negotiation call.

Why fee leakage survives for years

Bank fees leak for a few very specific reasons, and none of them are exotic.

First, the descriptors on statements are deliberately vague. A "cash management fee" can bundle five separate things — positive pay, ACH origination, wire templates, account analysis, and a per-item charge. When it's one line, you can't tell what you're paying for or whether you even use the service.

Second, fees creep. A relationship that started at $12/month in maintenance quietly becomes $29 after a "product enhancement." Nobody sent a real notice, or if they did, it was page 14 of a disclosure PDF. The fee schedule you agreed to and the fee schedule you're actually paying diverge over time, and the drift is always in the bank's favor.

Third — and this is the one that surprises owners — many fees are waivable, but only if you ask. Banks maintain internal waiver authority for relationship managers. They won't volunteer it. A merchant who processes $40k/month and complains politely often gets fees reversed that a silent customer pays forever.

In practice, this usually happens when the person who opened the account left the company, and whoever inherited the banking relationship never saw the original pricing. The institutional memory of "what we agreed to pay" walks out the door with them.

The five-day plan at a glance

You don't need to do these on five consecutive days.

DayFocusOutput
Day 1Pull 12–24 months of transaction data and isolate fee linesA clean fee-only dataset
Day 2Map each fee to a category and expected rateFee-mapping table
Day 3Run reconciliation queries; flag anomaliesList of overcharges and duplicates
Day 4Model sweep/balance options; set action thresholdsDecision on what to move or cancel
Day 5Run the vendor call using the scriptReversals + new pricing agreement

But keep them close together — the momentum matters, and the data you pull on Day 1 goes stale if you wait a month.

Day 1: Get the data into a shape you can query

Export at least 12 months, ideally 24, of transactions from every business account and merchant processor you run. Most banks let you export CSV; if yours only offers PDF, you can still work with it but expect an hour of cleanup.

The goal is a single table with columns roughly like this:

  1. txn_date
  2. account_id
  3. description (the raw bank descriptor)
  4. amount
  5. txn_type (debit/credit)

Load it into whatever you're comfortable with — Postgres, SQLite, even a spreadsheet if the volume is small. Then isolate the fee lines. Fees almost always share descriptor patterns.

Process diagram

Then isolate the fee lines. Fees almost always share descriptor patterns.

SELECT txndate, accountid, description, amount FROM banktransactions WHERE txntype = 'debit' AND ( description ILIKE '%fee%' OR description ILIKE '%charge%' OR description ILIKE '%svc%' OR description ILIKE '%analysis%' OR description ILIKE '%maint%' OR description ILIKE '%wire%' OR description ILIKE '%overdraft%' OR description ILIKE '%nsf%' ) ORDER BY description, txn_date;

Don't trust this to catch everything. Some banks use codes with no readable word at all. After running the pattern filter, eyeball the full debit list sorted by recurring amounts — a fixed $25.00 hitting on the same day each month is a fee even if the descriptor says nothing.

One thing worth internalizing: the fees that hurt most are rarely the big one-time ones. They're the small recurring ones nobody questions because each individual charge feels too trivial to fight.

Day 2: Build the fee-mapping table

This is the core of the whole exercise. You're creating a reference table that maps every fee you pay to a category, a benchmark, and a yes/no on whether you actually use the underlying service.

Descriptor (raw)CategoryFrequencyCurrent amountExpected/benchmarkDo we use it?
ACCT ANALYSIS FEEAccount maintenanceMonthly$29$0–$15Yes
MERCHANT SVC 0042Card processingMonthly$99 + %~2.4% eff.Yes
ACH ORIG BATCHACH originationPer batch$0.30$0.10–$0.25Yes
WIRE OUT DOMESTICWire transferPer wire$30$15–$25Sometimes
POSITIVE PAYFraud controlMonthly$40$20–$35Unsure
RETURNED ITEM FEEExceptionPer event$12avoidableNo (should be)

The "Do we use it?" column is where money hides. Positive pay, lockbox services, remote deposit modules, wire templates set up once for a vendor you no longer work with — businesses pay for capabilities they abandoned. If you can't confidently say what a line does for you, mark it unsure and put it on the negotiation list.

Compute the effective rate: total fees for the month divided by total card volume.

For merchant processing, don't compare the headline rate. Compute your effective rate: total fees for the month divided by total card volume. A processor advertising "2.6%" that also charges $99/month, a PCI fee, a statement fee, and a batch fee might have an effective rate above 3% once you're doing real volume. The effective rate is the only number that matters.

Day 3: Reconciliation queries that surface the real problems

Now you compare what you're actually paying against what the mapping table says you should pay. A few queries do most of the work.

Find duplicate charges in the same period. Banks occasionally double-bill, especially after a system migration on their end.

SELECT accountid, description, amount, DATETRUNC('month', txndate) AS mth, COUNT() AS hits FROM banktransactions WHERE txntype = 'debit' GROUP BY accountid, description, amount, DATETRUNC('month', txndate) HAVING COUNT() > 1 ORDER BY mth DESC;

Detect fee creep month over month. This surfaces the quiet increases.

SELECT description, DATETRUNC('month', txndate) AS mth, SUM(amount) AS monthlytotal, LAG(SUM(amount)) OVER ( PARTITION BY description ORDER BY DATETRUNC('month', txndate) ) AS prevmonth FROM banktransactions WHERE txntype = 'debit' AND description ILIKE '%fee%' GROUP BY description, DATETRUNC('month', txndate) ORDER BY description, mth;

Wherever monthlytotal jumps above prevmonth with no volume change, you've found a rate increase worth challenging.

Annualize each fee category. This is the pivot that changes minds. A $29 monthly fee feels like nothing until you see it as $348/year, and the whole stack as one number.

SELECT CASE WHEN description ILIKE '%analysis%' OR description ILIKE '%maint%' THEN 'Maintenance' WHEN description ILIKE '%wire%' THEN 'Wires' WHEN description ILIKE '%ach%' THEN 'ACH' WHEN description ILIKE '%nsf%' OR description ILIKE '%overdraft%' THEN 'Exceptions' WHEN description ILIKE '%merchant%' OR description ILIKE '%svc%' THEN 'Card processing' ELSE 'Other' END AS feecategory, SUM(amount) AS trailing12mo FROM banktransactions WHERE txntype = 'debit' AND txndate >= CURRENTDATE - INTERVAL '12 months' GROUP BY 1 ORDER BY trailing_12mo DESC;

If you'd rather stay in a spreadsheet, the same output comes from a pivot table: rows = your category column, values = SUM of amount, filter = last 12 months. Same insight, less setup.

The pattern that shows up consistently: exception fees (NSF, overdraft, returned items) are almost entirely self-inflicted and fixable with better cash timing, and card processing is usually the single biggest category people ignore because they assume the rate is fixed.

Day 4: Action thresholds and how sweep accounts actually work

Data without thresholds just becomes another report nobody acts on. Decide in advance what triggers action so you're not re-litigating every line.

  1. Any single unexplained fee > $25/month → challenge or cancel.
  2. Any fee category > $500/year → benchmark and negotiate.
  3. Effective card rate > 2.9% → get a competing quote.
  4. More than 2 exception fees (NSF/overdraft) per quarter → fix cash timing, not just the fees.
  5. Any charge for a service marked "unsure" or "don't use" → cancel immediately.

That last one is the fastest win. Canceling a positive-pay module you never configured is a phone call, not a negotiation.

Sweep accounts, plainly

A sweep account automatically moves idle balances between your operating account and an interest-bearing or investment account overnight, then sweeps enough back in the morning to cover clearing items.

Earnings credit / interest offset. Many business checking accounts use an earnings credit rate (ECR) — the bank effectively pays you interest in the form of fee waivers based on your average balance. If you're holding a large operating balance and still paying account analysis fees, you may be leaving earnings credit unclaimed. Ask your banker for your ECR and your average collected balance; if the credit should be covering your fees and isn't, that's a negotiation point.

Overdraft prevention. A properly configured sweep pulls funds from a linked reserve to cover shortfalls, killing NSF and overdraft fees that otherwise trigger at around $35 a pop.

The trap with sweeps: some banks charge a monthly sweep-service fee that quietly exceeds the interest or credit you earn on a modest balance. Run the math. If your average idle balance is $80k and the sweep earns you an extra ~$150/month but the service costs $75/month, it's worth it. If your idle balance is $15k, the sweep fee eats the benefit. Sweeps make sense above a balance threshold, not automatically.

If part of your leakage comes from overdrafts caused by unpredictable timing, the deeper fix is a forecast you actually watch. A 13-week rolling cash-forecast system tells you the days you'll be tight before the bank does, and pairing that with rules that gate AR/AP timing decisions removes most self-inflicted exception fees at the source.

Day 5: The vendor-negotiation script

You have your annualized numbers, your list of overcharges, and your "we don't use this" cancellations. Now you call your relationship manager. Ask for them by name — do not settle for the general service line, because the general line has no waiver authority.

Here's the actual flow:

Opening: > "Hi [Name], I've been going through our fee history for the last 12 months and I've got a few things I need to sort out on the account. I'd like to walk through them together — some look like they need correcting, and a couple I want to renegotiate. Do you have ten minutes?"

For duplicates/errors: > "On [month], I'm seeing the [descriptor] charged twice. Same amount, same period. Can you pull that up and reverse the duplicate?"

For fee creep: > "The account analysis fee was $12 last year and it's $29 now. Our balances and usage haven't changed. What drove that, and can we bring it back in line?"

For services you don't use: > "We're being billed $40/month for positive pay, but we've never actually configured or used it. I'd like that canceled and, if possible, credited back."

For the big renegotiation (card processing / maintenance): > "Our effective card rate is running about 3.1% on roughly $45k of monthly volume. I've got a competing quote closer to 2.5%. I'd rather stay with you — what can you do on the pricing?"

The close: > "So to confirm: you're reversing the duplicate, canceling positive pay with a credit, and reviewing the card rate. Can you send me that in writing today, and can we set a reminder to review the full fee schedule every six months?"

Two things make this work. One, you name specific dollar amounts and dates — vague complaints get vague answers. Two, you mention a competing quote for the big items. Banks have retention pricing they never show unless they think you'll leave.

Get everything in writing. A verbal waiver evaporates the moment your rep changes roles.

When this is worth doing — and when it isn't

When it makes sense: If you process meaningful card volume, run regular ACH or wires, carry any real operating balance, or have never audited your fee schedule since opening the account. Nearly every SMB in that group finds something.

When it's marginal: If you're a very small operation running a single low-balance account with a flat monthly fee and almost no transactions, the annual leakage might be $100–$200. Still worth one afternoon, not a full week.

Who should skip the sweep piece specifically: Businesses with consistently low idle balances. Sweeps only pay off above a balance threshold, and below it the service fee makes things worse.

A real scenario

A regional HVAC contractor — around 20 employees, roughly $3M in annual revenue — ran two operating accounts and a merchant processor for card payments on service calls. Nobody had touched the banking relationship in about four years.

Pulling 18 months of data surfaced four things: a "cash management" bundle at $65/month that included a lockbox service they'd stopped using, an account analysis fee that had crept from $15 to $34, a positive-pay charge for a module never configured, and an effective card rate of about 3.2% on roughly $50k of monthly volume.

The cleanup: canceling the lockbox and positive pay saved close to $105/month. The analysis fee got walked back to $18 after one call. The card rate, with a competing quote in hand, dropped to about 2.6% — worth roughly $300/month at their volume. Add a couple of reversed duplicate charges from a bank system migration, and total recovered leakage landed somewhere around $5,500–$6,000 a year. About a week of work, most of it on Days 1 and 3.

Nothing dramatic. Just money that had been quietly leaving for years because no one had ever sorted the statement into categories and asked.

Closing thought

Bank fee optimization for a small business isn't a one-time project you finish and forget — fees creep back, migrations reintroduce errors, and new services get added without much fanfare. The real win from running this week isn't just the recovered dollars; it's the fee-mapping table you now own. Refresh it every six months, re-run the annualization query, and keep the negotiation script handy. The bank is counting on you not to look. Looking, twice a year, is the whole edge.

Built for Business Tailored for small to medium business financial workflows
Save Time Automate bookkeeping, invoicing, and reporting
Maintain Compliance Simplify tax filing and audit preparation
Drive Growth Gain financial insights to make strategic decisions