Why (Not) Build Yet Another Finance App — Part 1
Brazil's Open Finance is one of the best things that has happened to the industry. You authorize, the bank releases your data, the transactions show up.
In our heads, it was plug in an API and move on to the next feature.
Pluggy, our partner, does the heavy lifting of talking to dozens of financial institutions. Everything else was left for us. This is Part 1 of the diary we started in Part 0.
Quick context: Open Finance Brasil is the Central Bank's regulated system for sharing bank data with apps you authorize. Pluggy is the integrator that connects us to the banks.
What we thought it was
- The user authorizes in their bank's app
- The bank releases the data
- The transactions show up in our app
What it really was
Duplicates are a problem with no right answer
When you sync the same statement many times, you need to know what you already have. The obvious rule: same account, same day, same description, same amount, so it's the same transaction.
Until the day someone bought two things for R$ 41 at the same store, on the same day. The second purchase vanished. By our rule, it was a copy of the first.
The fix was to use the time of the transaction when the bank sends it, without breaking older transactions, which have no time at all.
The opposite problem happens too. At one bank, the same Pix transfer can arrive with different descriptions in different syncs. There, the rule has to be looser so it doesn't duplicate.
Too loose and you duplicate. Too strict and you delete real purchases.
Every fix on one side opens a risk on the other.
Some of our commits about duplicates, from February to August 2026 (several in Portuguese: "duplicate syncs", "investments duplicating on reconnect"). And the list goes on.
A new connection looks broken when it isn't
Right after someone connects their bank, the institution can take a while to release the data. During that time, the sync comes back empty. And we proudly showed: "Sync failed".
Imagine connecting your bank for the first time, in a new app, and seeing "failed". Worse: in some cases, a sync that had worked showed up as "interrupted", because a safety step in our code overwrote the correct status.
The failure message is now reserved for when it's real news.
Reconnecting is the most fragile moment
And reconnecting isn't an exception, it's routine. Open Finance integration is priced per connection: every bank each user connects counts. For the business to work, we need the freedom to remove connections that are no longer in use, like the one of someone who went back to the free plan. When that person comes back, they connect everything again.
When someone removes their bank and connects it again, a lot comes back with new identifiers. We've seen duplicated investments, accounts created again next to the old ones and, in a case that gets its own story in Part 4, credit card bills that went blank.
Every bank is its own case, and so is every user
opened with Pluggy
An institution that returns zero accounts right after someone connects. A bank that sends the same Pix transfer with different descriptions. An account that changes its name from one sync to the next. For cases like these, specific to one bank or one user, we open a ticket with Pluggy and investigate together.
There is no single "Open Finance" that works one way. There are dozens of institutions, each with its own quirks, and an integrator in the middle doing its best to make them look the same.
Disconnecting isn't simple either
When someone removes a connection, what do you do with two years of imported transactions? Deleting everything scares people who just wanted to switch banks. Keeping everything frustrates people who wanted out.
For months, we decided for the user. Now we ask, and show exactly how many transactions, accounts and investment records will go before they confirm.
What we did
- ✓Duplicates checked using the time, when the bank sends it.
- ✓Specific rules for banks that change the description of the same transaction.
- ✓A neutral message on the first connection, and automatic retries.
- ✓Old accounts reused when a connection is recreated.
- ✓An explicit choice when removing: just the connection, or the connection and its data.
What we haven't solved yet
We don't control when each institution releases data, or how it describes each transaction. When something breaks the pattern, the way forward is still to open another ticket and wait.
Open Finance consent expires and has to be renewed. Every flow that depends on the user going back to their bank's app loses people along the way.
And dedup is still a bet: we only find out a rule is wrong when someone complains about a purchase that vanished or showed up twice.
If you're building with Open Finance
Treat the first sync, reconnection and removal as three different products. That's where we spent the most time.
Want to see how it turned out? Create your Snabber account and connect your bank.
In the next part: charging for the app, or how Apple doesn't tell you a user canceled.
