Vibe Coding a FinTech App: Why This Is Especially Dangerous

#vibe coding FinTech
Sandor Farkas - Founder & Lead Developer at Wolf-Tech

Sandor Farkas

Founder & Lead Developer

Expert in software development and legacy code optimization

A founder in Frankfurt builds a payments feature over a weekend using Cursor and Claude. The code looks clean, the tests pass, and the logic feels right. Three months after launch, they discover that cumulative rounding errors have caused €0.01 discrepancies to accumulate across tens of thousands of transactions. The total divergence is €847. Worse, their transaction logs do not contain enough information to reconstruct which transactions are affected.

This is not a hypothetical. It is the category of problem that makes FinTech fundamentally different from vibe coding a content platform, a task manager, or even an e-commerce shop. In those domains, AI-generated code that "mostly works" produces bugs that annoy users. In financial software, bugs that "mostly work" move money incorrectly, expose you to regulatory fines, and in the worst cases implicate you in fraud facilitation.

The risks are specific and predictable. They are also almost impossible to catch without domain knowledge that large language models reliably lack.

The Money Problem: Floating-Point Arithmetic Is Not Currency Math

This is the most pervasive mistake in AI-generated financial code, and it appears in virtually every vibe-coded FinTech codebase I have reviewed. The problem is foundational: IEEE 754 floating-point arithmetic—which is what JavaScript's number type, PHP's float, and Python's float all use—cannot represent most decimal fractions exactly.

Run this in any JavaScript console:

console.log(0.1 + 0.2); // 0.30000000000000004

AI coding assistants know this. Ask them about currency handling and they will often generate code that uses toFixed(2) or Math.round(amount * 100) / 100 to paper over the imprecision. But these are display fixes, not calculation fixes. Apply them inside a loop of thousands of transactions, and errors compound. Apply them before multiplication, and you introduce new rounding errors. Apply them inconsistently across a codebase—which AI-generated code almost always does—and your totals do not add up.

The correct solution for financial applications is to work in the smallest indivisible unit of the currency (cents for EUR/GBP/USD, pence, öre) using integers, or to use a purpose-built arbitrary precision library. In PHP:

// Wrong — floating-point accumulation over thousands of transactions
$total = 0.0;
foreach ($transactions as $tx) {
    $total += $tx->getAmountEur(); // float
}

// Correct — integer arithmetic in minor units
$totalCents = 0;
foreach ($transactions as $tx) {
    $totalCents += $tx->getAmountCents(); // int, stored as cents
}
$displayTotal = number_format($totalCents / 100, 2);

In JavaScript/TypeScript, the standard library for this is decimal.js or dinero.js. Neither will appear in vibe-coded output by default. The AI defaults to native number because native number is what all of its training data on JavaScript arithmetic uses.

The audit fix is not just swapping types. It requires checking every point where monetary values are read from a database, passed between functions, serialized to JSON, and stored back—and ensuring that integer or decimal types are used consistently throughout the entire flow.

Regulatory Compliance Gaps That AI Cannot See

Large language models are trained on code. They are not trained on the operational experience of building systems that survive regulatory audits, because that knowledge lives in compliance documents, legal interpretations, and institutional memory—not in public GitHub repositories.

The result is that vibe-coded FinTech applications typically have correct-looking logic that violates regulatory requirements in ways that are invisible until an auditor or a payment processor's compliance team looks at the system.

PSD2 and Strong Customer Authentication

The EU's Revised Payment Services Directive (PSD2) mandates Strong Customer Authentication (SCA) for most electronic payments within the EEA. SCA requires at least two of three factors: something the customer knows (password/PIN), something they has (device, hardware token), and something they is (biometrics). Specific transaction categories are exempt—low-value payments, trusted beneficiaries, low-risk transactions assessed by the acquirer.

AI-generated checkout flows will implement OAuth or JWT authentication correctly. They will almost certainly not implement SCA step-up authentication, the PSD2 exemption logic, or the 3DS2 challenge flow that card networks require for SCA compliance. These are not features you add after the fact. They determine your payment architecture from day one.

Launching a European payments product without SCA does not merely create a security gap. It can cause your payment processor to block your account and expose you to fines from national financial regulators.

PCI DSS and Card Data Handling

PCI DSS (Payment Card Industry Data Security Standard) prohibits storing certain card data elements after authorization—including the full card number (PAN) except in hashed or truncated form, the CVV/CVC in any form, and the full magnetic stripe data. Violating PCI DSS can result in fines from card networks and termination of your payment processing agreement.

Vibe-coded payment flows frequently log card numbers in error messages, store them in debug fields, or pass them through application layers that do not need them. The AI generates code that handles the data it receives, not code that deliberately limits which data it touches. Proper tokenization architecture—where card data never touches your application servers and only a token referencing the card is stored—requires deliberate design that AI-generated code will not produce spontaneously.

AML and Transaction Monitoring

Anti-Money Laundering (AML) regulations in Germany and across the EU (6AMLD, and the forthcoming AMLA) require financial service providers to monitor for suspicious transaction patterns, maintain records for five to ten years, and file suspicious activity reports. These are not features—they are legal obligations that carry criminal liability for executives in some jurisdictions.

AI-generated financial code produces none of this infrastructure. A founder who builds a peer-to-peer payment feature over a weekend will not have AML monitoring in place, may not even know it is required, and will discover the gap only when onboarding with a regulated payment partner who reviews their technical architecture.

Transaction Integrity: Where AI-Generated Code Gets ACID Wrong

Database transactions are where AI-generated financial code most reliably fails under load. The failure modes are subtle in development and catastrophic in production.

Consider a transfer between two accounts: debit account A, credit account B. Correct implementation wraps both operations in a single database transaction so that either both succeed or neither do. AI-generated code frequently gets the wrapping right. What it misses is everything else:

// What AI typically generates — looks correct, has serious gaps
public function transfer(int $fromAccountId, int $toAccountId, int $amountCents): void
{
    $this->db->beginTransaction();
    try {
        $from = $this->accountRepo->find($fromAccountId);
        $to = $this->accountRepo->find($toAccountId);
        
        $from->debit($amountCents);
        $to->credit($amountCents);
        
        $this->db->commit();
    } catch (\Exception $e) {
        $this->db->rollBack();
        throw $e;
    }
}

// What production-grade financial code requires
public function transfer(int $fromAccountId, int $toAccountId, int $amountCents): void
{
    $this->db->beginTransaction();
    try {
        // SELECT ... FOR UPDATE — pessimistic locking prevents concurrent modification
        $from = $this->accountRepo->findForUpdate($fromAccountId);
        $to = $this->accountRepo->findForUpdate($toAccountId);
        
        if ($from->getBalanceCents() < $amountCents) {
            throw new InsufficientFundsException();
        }
        
        $from->debit($amountCents);
        $to->credit($amountCents);
        
        // Immutable audit record — never updated, only appended
        $this->ledgerRepo->recordTransfer($from, $to, $amountCents);
        
        $this->db->commit();
    } catch (\Exception $e) {
        $this->db->rollBack();
        throw $e;
    }
}

The AI version has a race condition. Without SELECT FOR UPDATE (or equivalent optimistic locking with version checks), two concurrent transfers from the same account can both read the balance as sufficient, both succeed, and together overdraw the account. This is the double-spend problem, and it is not theoretical—it is reproducible under any meaningful load test.

The audit ledger entry is also non-optional. A mutable balance column in an accounts table is not a financial record. It is a running total. If something goes wrong—a bug, a corrupted transaction, a disputed charge—you need an immutable append-only log of every financial event to reconstruct the correct state. AI-generated code models account state as mutable data, because that is how almost all non-financial software models state.

Audit Trails: The Requirement That AI Never Generates

Every significant action in a financial system—balance change, permission grant, configuration update, failed authentication attempt—must be logged to an immutable audit trail with enough context to reconstruct what happened and prove it to a regulator.

This means:

  • Who performed the action (authenticated user identity, not just a session token)
  • What changed (before and after values, not just the new state)
  • When it happened (server-side timestamp, not client-supplied)
  • Why it was authorized (the permission or approval chain that permitted the action)
  • From where (IP address, device fingerprint)

AI-generated code produces application logs. Application logs capture errors and debugging information. They are not audit trails. They are typically mutable (log rotation deletes them), stored in the application layer (not segregated from application data), and not structured for the specific queries a compliance team will run during an investigation.

Building a compliant audit trail architecture requires deliberate decisions about storage (append-only tables or immutable object storage), retention periods (five to ten years for most EU financial regulations), access controls (auditors can read but not modify), and query infrastructure (audit events need to be searchable by user, by entity, and by time range efficiently at scale).

What a Professional FinTech Code Review Must Check

When Wolf-Tech reviews a vibe-coded financial application, these are the first places we look, because they are where problems are most reliably found:

Monetary representation: Every field and variable that holds a currency value. Are they integers (minor units), Decimal objects, or float? Are conversions performed consistently? Is there a typed Money value object that enforces correctness, or is raw arithmetic scattered across the codebase?

Transaction boundaries: Does every operation that touches multiple financial records run inside an explicit database transaction? Are locks acquired before balance reads to prevent concurrent modification? Are partial failure scenarios tested?

Regulatory touchpoints: Does the authentication flow implement SCA for in-scope transactions? Does card data handling follow a tokenization architecture? Is there AML transaction monitoring infrastructure, even basic thresholds?

Audit coverage: Is there an immutable ledger recording every balance change? Are sensitive administrative actions logged with full context? Is the audit storage separate from application storage and inaccessible to application-level processes?

Error handling and observability: Do payment processing failures produce actionable alerts, not just 500 errors? Are failed transactions in a state that can be safely retried, or does a retry risk duplication?

None of these checks can be automated by a linter or a static analysis tool. They require understanding the domain, knowing the regulatory environment, and having seen these failure modes before.

The Cost of Getting This Wrong

In a content platform, a bug discovered in production costs development time to fix and possibly some user trust. In a financial application, the costs are qualitatively different: regulatory fines, card network penalties, payment processor termination, and—for founders—potential personal liability under AML and other financial regulations.

The EU's GDPR fines for data breaches are well-known. Less discussed is that 6AMLD criminal liability for AML failures can extend to individuals, not just companies. A founder who builds and operates a payments feature without AML monitoring in place is not just at regulatory risk—they may be personally exposed.

This is not an argument against building FinTech products, or against using AI tools to move faster. It is an argument that financial applications require a code quality audit and professional review before they handle real money—not after.

Wolf-Tech has audited financial software for European FinTech founders, payment platforms, and companies integrating payment features into existing products. If you have a vibe-coded financial application approaching production, or an existing system you are not fully confident in, reach out at hello@wolf-tech.io or visit wolf-tech.io for a free consultation. A proper review is far cheaper than what happens when these failures surface in production.