DEV Community

Cover image for πŸš€ How to Create and Use RPC Functions in Supabase with Flutter (Step-by-Step Guide)
Codexlancers
Codexlancers

Posted on

πŸš€ How to Create and Use RPC Functions in Supabase with Flutter (Step-by-Step Guide)

🧠 Introduction
When building modern apps, you often need to perform complex database operations β€” like filtering data, calculating values, or combining multiple queries. Writing all this logic directly in your Flutter app can quickly become messy and inefficient.

That’s where RPC (Remote Procedure Call) functions in Supabase come in.

πŸ‘‰ RPC functions allow you to write SQL functions inside your database and call them directly from your app as if they were APIs.

βœ… Why use RPC functions in Supabase?

  • Keep business logic inside the database (cleaner architecture)
  • Reduce network calls (better performance)
  • Improve security (controlled access to data)
  • Reuse logic across multiple clients (Flutter, Web, etc.)

🧰 Prerequisites
Before we start, make sure you have:

  • βœ… A Flutter project set up
  • βœ… A Supabase project created
  • βœ… Supabase Flutter SDK installed
  • βœ… Basic knowledge of SQL (SELECT, WHERE, etc.)

βš™οΈ Step 1: Create an RPC Function in Supabase
Let’s say we have a tasks table and we want to fetch all completed tasks for a specific user.

πŸ—„οΈ Example Table: tasks
idtitleuser_idis_completed1Task A101true2Task B101false

🧾 SQL Function
Go to Supabase Dashboard β†’ SQL Editor, and run:

create or replace function get_completed_tasks(p_user_id uuid)
returns table (
  id uuid,
  title text,
  is_completed boolean
)
language sql
as $$
  select id, title, is_completed
  from tasks
  where user_id = p_user_id
    and is_completed = true;
$$;
Enter fullscreen mode Exit fullscreen mode

πŸ” Explanation (Simple)

  • create or replace function β†’ creates the RPC function
  • p_user_id β†’ input parameter
  • returns table β†’ defines output structure
  • select ... β†’ actual query logic

πŸ§ͺ Step 2: Test the Function in Supabase
Before using it in Flutter, test it.

Run this in SQL Editor:

select * from get_completed_tasks('your-user-id-here');
Enter fullscreen mode Exit fullscreen mode

βœ… Expected Output
You should see only completed tasks for that user.

πŸ“± Step 3: Call RPC Function in Flutter
Now let’s call this function from your Flutter app.

πŸ“¦ Add Supabase Dependency

dependencies:
  supabase_flutter: latest_version
Enter fullscreen mode Exit fullscreen mode

⚑ Initialize Supabase

await Supabase.initialize(
  url: 'YOUR_SUPABASE_URL',
  anonKey: 'YOUR_SUPABASE_ANON_KEY',
);
Enter fullscreen mode Exit fullscreen mode

πŸ”₯ Call RPC Function

final supabase = Supabase.instance.client;
Enter fullscreen mode Exit fullscreen mode
Future<List<dynamic>> getCompletedTasks(String userId) async {
  final response = await supabase.rpc(
    'get_completed_tasks',
    params: {'p_user_id': userId},
  );
  return response;
}
Enter fullscreen mode Exit fullscreen mode

🧠 Explanation

  • rpc() β†’ calls Supabase function
  • 'get_completed_tasks' β†’ function name
  • params β†’ must match SQL parameter names πŸ–₯️ Use in UI
FutureBuilder(
  future: getCompletedTasks(userId),
  builder: (context, snapshot) {
    if (!snapshot.hasData) {
      return CircularProgressIndicator();
    }
    final tasks = snapshot.data as List;
      return ListView.builder(
        itemCount: tasks.length,
        itemBuilder: (context, index) {
          final task = tasks[index];
          return ListTile(
            title: Text(task['title']),
            subtitle: Text("Completed"),
          );
        },
      );
    },
  );

Enter fullscreen mode Exit fullscreen mode

🌍 Real-World Use Case
Let’s say you’re building a Task Management App (like your current Flutter project πŸ‘€).

Instead of:

❌ Fetching all tasks
❌ Filtering in Flutter

You can:

βœ… Use RPC to fetch only required data
βœ… Improve performance and reduce app logic

πŸ’‘ Other Use Cases

  • Calculating total revenue
  • Fetching user-specific dashboards
  • Complex joins across tables
  • Role-based data filtering ⚠️ Common Mistakes ❌ 1. Parameter Name Mismatch
params: {'userId': userId} // WRONG

Enter fullscreen mode Exit fullscreen mode

βœ” Must match SQL:

p_user_id
Enter fullscreen mode Exit fullscreen mode

❌ 2. Forgetting Permissions (RLS)
If Row Level Security (RLS) is enabled:

πŸ‘‰ Make sure policies allow access

❌ 3. Returning Wrong Data Type
If your function returns:

returns json
Enter fullscreen mode Exit fullscreen mode

Then handle it properly in Flutter.

❌ 4. Not Testing in SQL First
Always test in Supabase before calling from Flutter.

🧠 Best Practices
βœ… Keep functions simple and focused
One function = one responsibility

βœ… Use meaningful names

get_user_tasks βœ”
fetch_data ❌
Enter fullscreen mode Exit fullscreen mode

βœ… Secure with RLS policies
Don’t expose sensitive data

βœ… Use indexes for performance
Especially for large datasets

βœ… Prefer SQL functions over multiple API calls
Cleaner + faster

🏁 Conclusion
RPC functions in Supabase are a powerful way to move logic closer to your database, making your Flutter apps:

  • ⚑ Faster
  • 🧹 Cleaner
  • πŸ” More secure By following this step-by-step guide, you can now:

βœ” Create SQL functions
βœ” Test them in Supabase
βœ” Call them seamlessly from Flutter

πŸš€ Next Steps
Add pagination to your RPC functions
Use PostgreSQL joins inside functions
Explore Edge Functions vs RPC
Build reusable backend logic library
If you’re building scalable Flutter apps with Supabase, mastering RPC is a game changer πŸ’₯

Top comments (0)