Implement fraud detection in FlutterFlow by intercepting transactions in a Cloud Function before processing. The function extracts behavioral features (login frequency, device changes, amount vs history), sends them to a hosted ML model on Vertex AI or SageMaker, receives a risk score (0.0-1.0), and makes a decision: score above 0.7 auto-blocks, 0.4-0.7 flags for manual review, below 0.4 proceeds. Store decisions in a fraud_events collection for admin review.
ML fraud detection: intercept transactions before they process
Rule-based fraud detection (block if amount > $1000, block if new country) catches obvious fraud but misses sophisticated attacks. Machine learning models identify patterns across multiple signals simultaneously: does this transaction fit the user's historical behavior? Has the device changed? Is the timing unusual? A trained ML model considers all these features at once and returns a probability score. This tutorial covers the full pipeline for FlutterFlow apps: extracting features from Firestore user activity, calling a hosted ML model via Cloud Function, routing the transaction based on the risk score, and building an admin review interface. The fraud detection logic lives entirely in Cloud Functions — FlutterFlow handles the user experience for blocked transactions and the admin review interface.
Prerequisites
- FlutterFlow project with Firebase Authentication, Firestore, and Cloud Functions (Blaze plan)
- An existing payment or transaction flow in the app that a Cloud Function can intercept
- A Vertex AI project on Google Cloud (for model hosting) or access to a pre-trained fraud model API
- Understanding of Cloud Functions and Firestore security rules
Step-by-step guide
Design the transaction and fraud event Firestore schema
Design the transaction and fraud event Firestore schema
Create two collections for the fraud detection system. The transactions collection stores each transaction: transactionId (auto-generated), userId (String), amount (Double), currency (String), merchantCategory (String), timestamp (Timestamp), deviceId (String: device fingerprint), ipAddress (String), location (GeoPoint), riskScore (Double: filled by fraud detection), riskDecision (String: 'allow', 'review', 'block'), status (String: 'pending', 'completed', 'blocked'). The fraud_events collection stores flagged items for review: eventId, transactionId, userId, riskScore, features (Map: the input features sent to the model), decision, reviewStatus (String: 'pending', 'cleared', 'confirmed_fraud'), reviewedBy (String UID), reviewedAt (Timestamp), notes (String). Admin queries fraud_events filtered by reviewStatus == 'pending' for the review queue.
Expected result: Transactions and fraud events collections are configured to capture both transaction data and fraud detection decisions.
Build the feature extraction logic in a Cloud Function
Build the feature extraction logic in a Cloud Function
Create a Cloud Function named extractFraudFeatures that takes a transaction object and userId. The function queries Firestore to build the feature vector: (1) Transaction velocity: count transactions by this user in the last 24 hours, (2) Amount anomaly: compare current amount to the user's 30-day average transaction amount, (3) Device consistency: check if the current deviceId matches the user's primary device, (4) Location anomaly: calculate distance in km between the current location and the user's most common location (use GeoPoint math), (5) Time pattern: compare current hour to the user's typical transaction hour distribution, (6) Account age days: days since the user's account was created (newer accounts are higher risk). Return these as a normalized feature array: [txVelocity, amountRatio, isNewDevice, locationDistanceKm, timeAnomaly, accountAgeDays]. These six features are the input to your ML model.
1// Cloud Function: extractFraudFeatures2const admin = require('firebase-admin');34async function extractFraudFeatures(userId, transaction) {5 const db = admin.firestore();6 const now = new Date();7 const oneDayAgo = new Date(now - 24 * 60 * 60 * 1000);8 const thirtyDaysAgo = new Date(now - 30 * 24 * 60 * 60 * 1000);910 // 1. Transaction velocity (last 24 hours)11 const recentTxSnap = await db.collection('transactions')12 .where('userId', '==', userId)13 .where('timestamp', '>=', oneDayAgo)14 .get();15 const txVelocity = recentTxSnap.size;1617 // 2. Amount anomaly ratio18 const historySnap = await db.collection('transactions')19 .where('userId', '==', userId)20 .where('timestamp', '>=', thirtyDaysAgo)21 .get();22 const amounts = historySnap.docs.map(d => d.data().amount);23 const avgAmount = amounts.length > 024 ? amounts.reduce((a, b) => a + b, 0) / amounts.length25 : transaction.amount;26 const amountRatio = transaction.amount / avgAmount;2728 // 3. Device consistency29 const userDoc = await db.doc(`users/${userId}`).get();30 const primaryDevice = userDoc.data()?.primaryDeviceId || '';31 const isNewDevice = transaction.deviceId !== primaryDevice ? 1 : 0;3233 // 4. Account age in days34 const createdAt = userDoc.data()?.createdAt?.toDate() || now;35 const accountAgeDays =36 (now - createdAt) / (1000 * 60 * 60 * 24);3738 return {39 txVelocity,40 amountRatio,41 isNewDevice,42 accountAgeDays: Math.floor(accountAgeDays),43 features: [txVelocity, amountRatio, isNewDevice,44 accountAgeDays],45 };46}Expected result: The feature extraction function returns a normalized feature vector representing the transaction's risk context.
Call the ML model and implement the three-tier risk decision
Call the ML model and implement the three-tier risk decision
Create the main Cloud Function named checkFraud that orchestrates the full pipeline. It calls extractFraudFeatures, then sends the feature array to your ML model endpoint. For Vertex AI: make an authenticated POST to https://us-central1-aiplatform.googleapis.com/v1/projects/{projectId}/locations/us-central1/endpoints/{endpointId}:predict with the feature array. The model returns a fraud probability (0.0-1.0). For testing without a trained model, use Google Cloud's pre-built AutoML Tables or a simple rule-based score while you gather training data. Risk decisions: score >= 0.7 → block (return error to client, create fraud_event with reviewStatus 'pending'), score 0.4-0.69 → flag for review (allow transaction but create fraud_event, send admin notification), score < 0.4 → allow (log score on transaction, no action). Always store the riskScore and features on the transaction document for audit trail.
1// Cloud Function: checkFraud (main)2exports.checkFraud = functions.https.onCall(3 async (data, context) => {4 if (!context.auth) {5 throw new functions.https.HttpsError(6 'unauthenticated', 'User must be logged in');7 }89 const { transaction } = data;10 const userId = context.auth.uid;1112 // Extract features13 const { features, ...featureData } =14 await extractFraudFeatures(userId, transaction);1516 // Score with ML model (example: simple rule-based)17 // Replace with Vertex AI endpoint call in production18 let riskScore = 0.1;19 if (featureData.amountRatio > 5) riskScore += 0.4;20 if (featureData.isNewDevice === 1) riskScore += 0.2;21 if (featureData.txVelocity > 10) riskScore += 0.3;22 if (featureData.accountAgeDays < 7) riskScore += 0.2;23 riskScore = Math.min(riskScore, 1.0);2425 // Three-tier decision26 let decision;27 if (riskScore >= 0.7) {28 decision = 'block';29 } else if (riskScore >= 0.4) {30 decision = 'review';31 } else {32 decision = 'allow';33 }3435 // Store fraud event if flagged or blocked36 if (decision !== 'allow') {37 await admin.firestore().collection('fraud_events').add({38 userId, riskScore, decision,39 features: featureData,40 transactionData: transaction,41 reviewStatus: 'pending',42 createdAt: admin.firestore.FieldValue.serverTimestamp(),43 });44 }4546 if (decision === 'block') {47 throw new functions.https.HttpsError(48 'permission-denied',49 'Transaction blocked for security review');50 }5152 return { allowed: true, riskScore, decision };53 });Expected result: High-risk transactions are blocked before processing and logged for admin review; medium-risk are flagged.
Integrate fraud check into FlutterFlow transaction flows
Integrate fraud check into FlutterFlow transaction flows
In FlutterFlow's API Manager, create an API Call to your checkFraud Cloud Function (or use the callable function via a Custom Action with Cloud Functions SDK). On your payment or purchase button, modify the action flow to: (1) Call checkFraud with the transaction details — amount, merchant category, current device info, (2) Check the response: if the call returns an error (blocked), show a Dialog informing the user 'Transaction declined for security review. Contact support if you believe this is an error.' Do not say 'fraud' — use neutral language to avoid alarming legitimate users. If the response shows decision: 'review', proceed with the transaction but show a note 'This transaction is under review and may take additional time.' If decision is 'allow', proceed normally.
Expected result: Every transaction is scored before processing; blocked transactions show a user-friendly error message.
Build the admin fraud review queue in FlutterFlow
Build the admin fraud review queue in FlutterFlow
Create an admin-protected page in FlutterFlow named FraudReview. Protect it with a Conditional widget checking the current user's role == 'admin' (from their Firestore user document). Add a Backend Query on the fraud_events collection filtered by reviewStatus == 'pending', ordered by createdAt descending, real-time (Single Time Query: OFF). Add a ListView where each item shows: risk score (color-coded: red > 0.7, orange 0.4-0.7), user display name, transaction amount, which features triggered the high score, and the timestamp. Each item has two buttons: Clear (legitimate) and Confirm Fraud. The Clear button calls Update Document on the fraud_events doc setting reviewStatus: 'cleared', reviewedBy: currentUser.uid, reviewedAt: serverTimestamp(). The Confirm Fraud button sets reviewStatus: 'confirmed_fraud' and triggers a Cloud Function to suspend the user account. RapidDev has built fraud review dashboards for multiple FlutterFlow applications in the fintech space.
Expected result: Admin can review flagged transactions, clear false positives, and confirm fraud cases from the FlutterFlow admin dashboard.
Complete working example
1Fraud Detection Pipeline for FlutterFlow23FLOW:4 User initiates transaction5 → FlutterFlow calls checkFraud CF6 → CF extracts 6 features from Firestore7 → CF calls ML model endpoint8 → Model returns risk score 0.0-1.09 → CF applies decision:1011DECISION MATRIX:12 Score >= 0.7 → BLOCK13 - Throw HttpsError to FlutterFlow14 - Create fraud_event (reviewStatus: pending)15 - Show neutral block message to user1617 Score 0.4-0.7 → REVIEW18 - Allow transaction to proceed19 - Create fraud_event (reviewStatus: pending)20 - Alert admin (push notification / Slack)2122 Score < 0.4 → ALLOW23 - Store score on transaction record24 - No user impact2526FEATURES EXTRACTED:27 1. txVelocity - transactions in last 24h28 2. amountRatio - current / 30-day avg amount29 3. isNewDevice - 0 or 130 4. accountAgeDays - days since signup31 5. locationDist - km from usual location32 6. timeAnomaly - vs usual transaction hour3334FIRESTORE COLLECTIONS:35 transactions/{id} - all transactions + riskScore36 fraud_events/{id} - flagged/blocked transactions37 reviewStatus: 'pending'|'cleared'|'confirmed_fraud'Common mistakes
Why it's a problem: Setting the fraud threshold too low, blocking too many legitimate users
How to avoid: Start with a conservative threshold (block only above 0.7, review 0.5-0.7). Measure your false positive rate in the first two weeks by reviewing cleared transactions. Gradually adjust the threshold based on actual data. Never optimize for catching 100% of fraud at the cost of significant false positives.
Why it's a problem: Running fraud detection after the payment has already been processed
How to avoid: Call checkFraud before calling your payment API (Stripe, PayPal, etc.). Only proceed to the payment API if checkFraud returns an allow or review decision. For Stripe, create the PaymentIntent only after the fraud check passes.
Why it's a problem: Exposing fraud detection logic or threshold values in client-side FlutterFlow code
How to avoid: Keep all fraud detection logic in Cloud Functions. FlutterFlow only sends the raw transaction data — the model endpoint, feature weights, and decision thresholds are never visible in the client app.
Best practices
- Build and maintain a training dataset of labeled fraud and legitimate transactions from day one — this data enables training a custom model as your app scales
- Log every fraud check decision (allow/review/block) with features for model retraining and audit compliance
- Implement step-up authentication for flagged transactions: instead of blocking, require additional verification (SMS OTP, selfie) for medium-risk transactions
- Set up admin alerts (push notification or Slack webhook) when a transaction is blocked so the team can respond to unusual fraud patterns immediately
- Use velocity checks as the first defense before calling expensive ML models — if a user makes 50 transactions in 10 minutes, block immediately without ML scoring
- Monitor your false positive rate weekly — if more than 2% of blocked transactions are cleared by admins, your thresholds are too aggressive
- Test fraud detection in staging with synthetic fraud scenarios before production deployment to catch both gaps and over-blocking issues
Still stuck?
Copy one of these prompts to get a personalized, step-by-step explanation.
I am building a Firebase Cloud Function for fraud detection in a FlutterFlow app. Write me the feature extraction function that takes a userId and transaction object and returns a fraud risk feature vector. The function should query Firestore to calculate: transaction count in last 24 hours, ratio of current amount to 30-day average, whether the device ID matches the user's primary device, and days since account creation. Return these as both individual named values and as a normalized array for ML model input.
Add fraud detection to my FlutterFlow payment flow. Before the Stripe payment button action proceeds, call my checkFraud Cloud Function with the transaction amount, userId, and device info. If the response is an error (transaction blocked), show a Dialog with the message 'For your security, this transaction requires additional review. Please contact support.' If the response contains decision: 'review', show a yellow banner saying 'This transaction is under review.' Otherwise proceed with the normal Stripe checkout action.
Frequently asked questions
Do I need a trained ML model to start fraud detection?
No. You can start with rule-based scoring (as shown in Step 3) that computes a risk score from your extracted features using business logic. A user making 20 transactions in 10 minutes, using a new device, and tripling their usual amount gets a high score. As you collect labeled fraud data from manual reviews, you can train a proper ML model (Vertex AI AutoML Tables works well for tabular fraud data) and replace the rule-based scoring while keeping the same interface.
How much does Vertex AI fraud detection cost?
Vertex AI AutoML Tables training costs approximately $20-50 for initial training on a dataset of 1,000-10,000 labeled transactions. Prediction calls cost about $0.002 per 1,000 predictions. For a typical app with 10,000 daily transactions, prediction costs are approximately $0.02 per day. The feature extraction Firestore reads (3-4 queries per transaction check) are the larger cost at scale — cache user history summaries to reduce read count.
What should I do when a legitimate user is incorrectly blocked?
Have a customer support path ready before launching fraud detection. When a user is blocked, show a support contact option alongside the block message. Your admin review queue (Step 5) lets support staff quickly review and clear false positives. When clearing a false positive, update the user's risk profile (lower their baseline score) and use the incident as a training example for model improvement.
How do I handle fraud detection for first-time users who have no transaction history?
New users have no history for feature extraction — amountRatio and velocity cannot be calculated. Apply conservative defaults for first-time users: set amountRatio to 1.0 (neutral), set txVelocity to 0 (no history). Weight the accountAgeDays feature more heavily for new accounts — accounts under 7 days old are higher risk regardless of transaction patterns. Consider requiring email verification or phone number confirmation before allowing the first transaction above a threshold amount.
What if I need help building a complete fraud detection system for my FlutterFlow app?
Building a production-grade fraud detection system with ML model training, feature engineering, and admin review workflows requires specialized backend expertise. RapidDev has built fraud detection pipelines for FlutterFlow apps in fintech, marketplace, and e-commerce contexts and can implement the full system including Vertex AI model training and admin tooling.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation