Connect FlutterFlow to AWS Lambda using a FlutterFlow API Call pointed at a Lambda Function URL or API Gateway endpoint. Lambda has no native FlutterFlow panel — you expose your function over HTTPS, then define it as a REST API Group in FlutterFlow's API Calls tab. The core pattern: Lambda holds your AWS credentials and secret keys server-side, FlutterFlow calls Lambda, Lambda does the AWS work and returns results to the app.
| Fact | Value |
|---|---|
| Tool | AWS Lambda |
| Category | Database & Backend |
| Method | FlutterFlow API Call |
| Difficulty | Intermediate |
| Time required | 45 minutes |
| Last updated | July 2026 |
Using AWS Lambda as a Secure Backend Proxy for Your FlutterFlow App
FlutterFlow compiles to a Flutter client app running on the user's device. This means any AWS access key you put in your project — in an API Call header, a Dart constant, or app state — ships to every user. AWS credentials in client code are a severe security risk and violate AWS terms of service. Lambda solves this: your function runs inside AWS's infrastructure with an IAM execution role that carries the permissions, so the actual AWS credentials never leave AWS's servers. FlutterFlow talks to Lambda over a public HTTPS URL, sending only the data the function needs from the user, and Lambda does all the privileged AWS work (DynamoDB queries, S3 uploads, SES emails, etc.) server-side.
The quickest way to expose a Lambda function to FlutterFlow is a Lambda Function URL. Available for all Lambda functions, a Function URL gives you a permanent HTTPS endpoint with no extra infrastructure. You choose between two auth modes: NONE (public, anyone with the URL can call it — protect with a shared-secret header) or AWS_IAM (requires SigV4 request signing, which is impractical to implement from FlutterFlow's API Calls tab). For most FlutterFlow use cases, NONE auth with a custom shared-secret header in the FlutterFlow API Group is the right choice.
For more advanced scenarios — rate limiting, per-user quotas, OAuth2/JWT validation, custom domain — place Lambda behind API Gateway. API Gateway adds a request/response layer, lets you issue API keys to clients, and handles throttling at up to 10,000 requests per second by default. The FlutterFlow API Group setup is the same either way: you point at the HTTPS URL and pass any auth header. Lambda's free tier includes 1 million requests and 400,000 GB-seconds per month, making it cost-effective for apps with moderate traffic.
Integration method
FlutterFlow has no AWS SDK or native Lambda panel — Lambda functions are called over HTTPS like any other REST API. You expose your Lambda function using a Lambda Function URL (the simplest path) or place it behind API Gateway for authentication and throttling. In FlutterFlow, you create an API Group pointing at the function's base URL, define POST or GET calls with any required headers or body parameters, and trigger them from the Action Flow Editor. Lambda acts as the secure backend: it holds your AWS credentials and third-party secrets, performs the server-side work, and returns a clean JSON response to the app.
Prerequisites
- An AWS account with permission to create Lambda functions and Function URLs (or API Gateway)
- A FlutterFlow project (any plan)
- A Lambda function already created and deployed in AWS with the logic you want to run
- The Lambda function configured to return JSON responses (Content-Type: application/json)
- For web builds: CORS configured on the Function URL or API Gateway before testing in FlutterFlow's browser-based Run mode
Step-by-step guide
Deploy your Lambda function and enable a Function URL
In the AWS Lambda console, open your function and click the 'Configuration' tab, then 'Function URL' in the left sidebar. Click 'Create function URL.' Set Auth type to 'NONE' (you will add your own shared-secret header for security in the next step). Under CORS settings, if you plan to test in FlutterFlow's web Run mode (which runs in a browser), enable CORS: set 'Allow origin' to `*` or your specific domain, 'Allow headers' to `Content-Type, X-Api-Key` (or whatever header name you choose for your shared secret), and 'Allow methods' to `POST, GET, OPTIONS`. Click 'Save.' AWS displays the Function URL — it looks like `https://abcdef1234567890.lambda-url.us-east-1.on.aws/`. Copy this URL; you will use it as the base URL in FlutterFlow. Important: a Function URL with NONE auth is public by URL knowledge — anyone who knows the URL can call it. The shared-secret header you add in the next step is the access control layer. For production apps with sensitive data, consider placing the function behind API Gateway with API key validation instead.
1// Minimal Lambda handler that returns JSON2// Runtime: Node.js 20.x3exports.handler = async (event) => {4 // Parse the request body from FlutterFlow5 const body = JSON.parse(event.body || '{}');6 const userInput = body.inputText || '';78 // Verify the shared secret header9 const secret = event.headers['x-api-key'] || '';10 if (secret !== process.env.SHARED_SECRET) {11 return {12 statusCode: 401,13 headers: { 'Content-Type': 'application/json' },14 body: JSON.stringify({ error: 'Unauthorized' })15 };16 }1718 // Your business logic here19 const result = `Processed: ${userInput}`;2021 return {22 statusCode: 200,23 headers: {24 'Content-Type': 'application/json',25 'Access-Control-Allow-Origin': '*'26 },27 body: JSON.stringify({ output: result })28 };29};Pro tip: Set your SHARED_SECRET as a Lambda environment variable in the AWS console (Configuration → Environment variables) — never hardcode it in your function code.
Expected result: The Function URL is active. Testing it with a POST request via a tool like Postman returns your expected JSON response with a 200 status.
Create a FlutterFlow API Group pointing at the Function URL
In your FlutterFlow project, click 'API Calls' in the left navigation toolbar (it looks like a plug or connection icon). Click '+ Add' and choose 'Create API Group.' Give the group a name that matches your Lambda function — for example 'LambdaBackend' or 'AIProxy.' In the 'Base URL' field, paste your Lambda Function URL: `https://abcdef1234567890.lambda-url.us-east-1.on.aws`. Do not include a trailing slash. Now add your shared-secret header to the API Group so it applies to all calls in this group. Click the 'Headers' tab inside the API Group editor. Click '+ Add Header,' set the name to `X-Api-Key` (or whatever header name you chose in your Lambda handler), and set the value type to 'Value' — then paste your shared secret value. Since this is a security header and FlutterFlow API Call headers ship in the compiled app, use a value that is not a high-privilege AWS credential — it is just a shared secret that gates access to your Lambda, not an AWS access key. Click 'Save.' The API Group is now configured as a container for individual API Calls that all share this base URL and auth header.
1{2 "api_group_name": "LambdaBackend",3 "base_url": "https://<your-function-url>.lambda-url.<region>.on.aws",4 "headers": [5 {6 "name": "Content-Type",7 "value": "application/json"8 },9 {10 "name": "X-Api-Key",11 "value": "<your-shared-secret>"12 }13 ]14}Pro tip: The shared secret in the FlutterFlow API Group header will be visible to determined users who decompile the app. For truly sensitive operations, use API Gateway with proper IAM or JWT-based authentication instead of a shared secret.
Expected result: The API Group 'LambdaBackend' appears in your API Calls panel with the base URL and shared-secret header configured. No individual calls are added yet.
Add a POST API Call, define variables, and test the response
Inside the 'LambdaBackend' API Group, click '+ Add' and choose 'Create API Call.' Name the call descriptively — for example 'ProcessUserInput.' Set the method to POST. In the 'Endpoint' field, enter the path after your base URL: if your function handles everything at the root, leave this blank or enter `/`. Click the 'Variables' tab. Here you define the dynamic parts of your request that will be filled in from app state at runtime. Click '+ Add Variable,' name it `inputText` (matching the field name your Lambda expects in the request body), set its type to String, and mark it as required. Now click the 'Body' tab and set the body type to JSON. In the JSON body field, reference your variable using double curly brace syntax: `{ "inputText": "{{inputText}}" }`. FlutterFlow will substitute the variable at runtime. Click 'Response & Test.' Scroll down to the 'Test' section and enter a test value for inputText. Click 'Test API Call.' If your Lambda is running correctly, the response panel shows the JSON your function returned. Click 'Generate JSON Paths' to let FlutterFlow automatically create JSON path extractors for each field in the response (for example, `$.output` maps to the 'output' field). These paths let you bind response data to widgets.
1{2 "api_call_name": "ProcessUserInput",3 "method": "POST",4 "endpoint": "/",5 "variables": [6 { "name": "inputText", "type": "String", "required": true }7 ],8 "body": {9 "inputText": "{{inputText}}"10 },11 "response_json_paths": [12 { "field": "output", "path": "$.output", "type": "String" }13 ]14}Pro tip: If the test returns a CORS error in the test panel, it means your Lambda Function URL's CORS configuration is not set up correctly. Go back to the Lambda console → Configuration → Function URL and confirm 'Allow origin' includes your test origin or `*`.
Expected result: The test in FlutterFlow's API Calls panel returns a 200 response with your Lambda's JSON body. JSON Paths are generated for each field. The call is ready to be used in the Action Flow Editor.
Trigger the Lambda call from a widget action and display the result
Now wire the API Call to your app's UI. Navigate to the page where you want the Lambda call to happen — for example, a page with a TextField for input and a Button to submit. Click the Button to select it. In the right panel, click 'Actions' to open the Actions panel, then click '+ Add Action.' In the action picker, choose 'Backend/Database → API Request.' In the dropdown, select your API Group ('LambdaBackend') and then your specific call ('ProcessUserInput'). A field for each variable you defined appears. For the `inputText` variable, click the variable picker (the orange square icon) and choose 'Widget State → [YourTextField] → Value' to pull the text the user typed. Click 'Confirm.' Now add a second action to store or display the result: after the API Call action, add 'Update App State' or set a page variable using the response data. Choose the JSON path you extracted (for example, '$.output') as the value. Bind a Text widget on the page to this state variable so the Lambda result appears when the call completes. In the Action Flow Editor, you can also add an 'Is Loading' state to show a loading spinner while the call is in flight — important for Lambda cold starts, which can add 1–3 seconds to the first call of a function that has been idle.
Pro tip: Lambda's default timeout is 3 seconds (configurable up to 15 minutes). For any operation that might take more than 2-3 seconds, increase the timeout in the Lambda console (Configuration → General configuration) and show a loading state in FlutterFlow so users know the request is in progress.
Expected result: Tapping the button triggers the Lambda call. The result text from Lambda's JSON response appears in the bound Text widget on the page. The loading spinner (if added) shows while the call is in flight and hides when the response arrives.
Harden with API Gateway for production apps (optional but recommended)
If your app will see real user traffic, consider replacing the Function URL with API Gateway for better access control. In the AWS console, go to API Gateway → Create API → REST API. Define a resource (for example, `/process`) and a POST method. Set the integration type to 'Lambda Function' and point it at your function. Under 'Method Request,' enable 'API Key Required.' In the API Gateway console, create a Usage Plan with throttling limits (for example, 1,000 requests per second, 10,000 per day) and an API key. Associate the API key with the Usage Plan and the Usage Plan with your stage. The client (FlutterFlow) now sends the API key in the `X-Api-Key` header — API Gateway validates it before the request reaches Lambda, preventing unauthorized calls even if the key leaks. Update your FlutterFlow API Group base URL to the API Gateway invoke URL (looks like `https://<api-id>.execute-api.<region>.amazonaws.com/<stage>`). This setup gives you throttling, per-key quotas, CloudWatch logging, and the ability to rotate keys without redeploying Lambda. If you want help designing the API Gateway auth layer, RapidDev's team builds FlutterFlow + AWS integrations regularly — free scoping call at rapidevelopers.com/contact.
Pro tip: After creating the API Gateway stage, enable CloudWatch logging on the stage (Stage → Logs/Tracing tab). This gives you per-request logs you can inspect in the AWS CloudWatch console when debugging FlutterFlow call failures.
Expected result: API Gateway shows the stage deployed and the API key active. Calling the FlutterFlow API Group with the new URL returns the same Lambda response but now goes through API Gateway's auth and throttling layer.
Common use cases
E-commerce app that generates S3 presigned upload URLs
A FlutterFlow app lets sellers upload product photos. Instead of putting AWS credentials in the app, a Lambda function receives the file name and content type, generates a presigned S3 URL using the Lambda execution role, and returns it. The app uses that URL to upload directly to S3 without needing any AWS credentials client-side.
When a seller taps 'Upload Photo,' call a Lambda function that returns a presigned S3 URL. Then upload the file directly from the device to S3 using that URL.
Copy this prompt to try it in FlutterFlow
AI-powered chat feature using an LLM API with a secret key
A FlutterFlow app sends user messages to a Lambda function. Lambda holds the OpenAI or Anthropic API key in an environment variable, calls the LLM API, and streams or returns the response to the app. The secret key never appears in the FlutterFlow project.
Build a chat screen that sends user messages to an AI assistant. The AI API key must stay private — use a Lambda function to make the call and return the response.
Copy this prompt to try it in FlutterFlow
Notification app that triggers DynamoDB queries and SES emails
A FlutterFlow admin app triggers a Lambda function on button tap. Lambda queries a DynamoDB table for users who meet a condition, formats a message, and sends bulk emails via SES. FlutterFlow only passes the message template text — all AWS service interactions happen inside Lambda with no AWS credentials in the app.
Build an admin screen where I can enter a message and tap 'Send to all active users.' A Lambda function should look up active users in DynamoDB and send each one an email via SES.
Copy this prompt to try it in FlutterFlow
Troubleshooting
API Call test in FlutterFlow returns 'XMLHttpRequest error' or CORS error in web Run mode
Cause: Lambda Function URLs and API Gateway do not send CORS headers by default. FlutterFlow's browser-based Run mode enforces browser CORS policy, which rejects responses without the correct Access-Control-Allow-Origin header. Native iOS/Android builds are not affected by CORS.
Solution: In the Lambda console, go to your function's Configuration → Function URL → Edit CORS settings. Add 'Allow origin: *', 'Allow headers: Content-Type, X-Api-Key', and 'Allow methods: POST, GET, OPTIONS'. If using API Gateway, go to your resource and enable CORS from the Actions menu. After saving, also ensure your Lambda handler returns the Access-Control-Allow-Origin header in its response object.
1// Add to every Lambda response2return {3 statusCode: 200,4 headers: {5 'Content-Type': 'application/json',6 'Access-Control-Allow-Origin': '*',7 'Access-Control-Allow-Headers': 'Content-Type, X-Api-Key'8 },9 body: JSON.stringify({ output: result })10};Lambda call returns 401 Unauthorized even though the API key header looks correct
Cause: The header name or value in FlutterFlow does not exactly match what the Lambda handler checks. Header names are case-insensitive in HTTP but the comparison in your Lambda code may be case-sensitive.
Solution: In your Lambda handler, normalize the header name before comparing: `const secret = event.headers['x-api-key'] || event.headers['X-Api-Key'] || '';`. AWS API Gateway lowercases all header names before passing them to Lambda, so check `event.headers['x-api-key']` (lowercase). Also confirm the secret value in FlutterFlow's API Group header has no trailing spaces.
1// Safe header extraction — handles both cases2const secret = (event.headers['x-api-key'] || event.headers['X-Api-Key'] || '').trim();3if (secret !== process.env.SHARED_SECRET) {4 return { statusCode: 401, body: JSON.stringify({ error: 'Unauthorized' }) };5}Lambda call works in FlutterFlow test panel but times out or returns 5xx on device
Cause: Lambda's default timeout is 3 seconds. If the function does slow work (external API calls, DynamoDB queries on large tables), it can exceed the timeout and return a 5xx error to FlutterFlow instead of a clean response.
Solution: In the Lambda console, go to Configuration → General configuration → Edit and increase the Timeout to a realistic value for your function's workload (e.g., 30 seconds for API calls, up to 15 minutes maximum). In FlutterFlow, add an 'Is Loading' state that shows a spinner while the call is in progress so users do not tap again and trigger a duplicate call.
First call after the app is idle takes 3+ seconds but subsequent calls are fast
Cause: Lambda cold start — when a function has not been invoked recently, AWS needs to spin up a new execution environment. This adds 1–3 seconds of latency on the first call.
Solution: Add a loading indicator in FlutterFlow for all Lambda calls so users see a spinner rather than a frozen UI. For latency-sensitive features (like real-time AI responses), consider enabling Lambda Provisioned Concurrency in the AWS console to keep at least one execution environment warm at all times. This has a cost but eliminates cold starts.
Best practices
- Never put AWS access keys or secret keys in FlutterFlow API Call headers or Dart code — Lambda's IAM execution role carries the AWS permissions server-side, so credentials never need to be client-side.
- Use NONE auth on Function URLs only with a shared-secret header as a gate — for production apps with sensitive data, use API Gateway with API key validation and a usage plan to enforce rate limits.
- Always configure CORS on the Function URL or API Gateway before testing in FlutterFlow's web Run mode — browser CORS policy will block calls that work fine on native device builds.
- Set Lambda timeout to at least double the maximum expected execution time of your function. FlutterFlow's API Call will return a generic error if Lambda times out, which is hard to debug without this context.
- Show a loading state in FlutterFlow for all Lambda API Calls — cold starts can add 1–3 seconds to the first call, and users need visual feedback that the request is in progress.
- Store Lambda's shared secret and all third-party API keys in Lambda Environment Variables (Configuration → Environment variables) — never hardcode them in function code or pass them from the FlutterFlow client.
- Test the Lambda function endpoint independently with a tool like Postman before adding it to FlutterFlow — this isolates whether a problem is in the Lambda logic or the FlutterFlow API Call configuration.
Alternatives
Choose Firebase Cloud Functions if you are already using Firebase for auth and Firestore — it has a native FlutterFlow integration panel, tighter auth integration, and no separate HTTPS endpoint configuration needed.
Choose Google Cloud Functions if you prefer Google's infrastructure but want to manage functions outside of Firebase — the setup is similar to Lambda but uses Google Cloud IAM.
Choose AWS S3 directly (via Lambda-generated presigned URLs) for file storage needs — Lambda is the correct proxy layer, and S3 handles the actual object storage in the AWS ecosystem.
Frequently asked questions
Can FlutterFlow sign requests with AWS SigV4 to use AWS_IAM auth on a Function URL?
Not practically. SigV4 signing requires computing an HMAC-SHA256 signature over the canonical request using your AWS access key and secret — this is complex multi-step logic that FlutterFlow's API Calls tab cannot do natively. You would need a custom Dart action with significant cryptographic code. The practical recommendation for FlutterFlow is to use NONE auth on the Function URL and protect the endpoint with a shared-secret header instead.
What is the difference between a Lambda Function URL and API Gateway — which should I use?
A Lambda Function URL is simpler: one click in the Lambda console gives you an HTTPS endpoint directly on the function. Use it for internal tools, prototypes, or when you control all callers. API Gateway adds a management layer with API key validation, per-key throttling quotas, custom domains, request/response transformation, and detailed CloudWatch logging. Use API Gateway for any Lambda endpoint that will receive traffic from a public app where you need rate limiting and access control.
How do I pass the logged-in user's identity from FlutterFlow to Lambda?
If you use Firebase Auth in FlutterFlow, you can pass the current user's Firebase ID token in a request header. In the FlutterFlow API Call variables, add a variable for the token and set its value from 'Authenticated User → ID Token' in the variable picker. In your Lambda handler, verify this token using the Firebase Admin SDK — this gives you the user's UID server-side without needing any additional auth mechanism.
Will Lambda costs be significant for a FlutterFlow app?
Lambda's free tier includes 1 million requests and 400,000 GB-seconds per month, which is enough for most early-stage and moderate-traffic apps. Beyond the free tier, Lambda costs approximately $0.20 per 1 million requests plus compute time based on memory allocation and duration. Most FlutterFlow use cases — proxy calls for AI or storage — are fast (under 1 second) and low-memory, keeping costs very low until you reach significant scale.
Talk to an Expert
Our team has built 600+ apps. Get personalized help with your project.
Book a free consultation