When to use DB functions vs Edge Functions in Supabase

Explore Supabase Database vs. Edge Functions—understand their differences, use cases, and best practices for scalable backend logic

supabase-database-vs-edge-functions
Baskaran Manimohan

Baskaran Manimohan

Founder, CloseFuture

Jul 15, 2025

Many developers initially approach Supabase as a modern alternative to Firebase or simply as a hosted PostgreSQL database with some extra conveniences. And while that’s true to an extent, stopping there means you're barely scratching the surface. Supabase offers a robust set of features that allow you to build full-stack applications without spinning up separate backend servers - and one of the most powerful tools in this ecosystem is Supabase Functions.

In this guide, we’ll explore the two main types of functions Supabase offers: Database Functions (PostgreSQL functions) and Edge Functions (serverless HTTP functions). We’ll cover what each type is, when and why to use one over the other, and walk through practical code examples and real-world use cases. We'll also talk performance considerations and best practices to help you build scalable, maintainable logic on top of your Supabase project.

1. What Are Supabase Functions?

Supabase supports two kinds of backend logic:

  1. Database Functions (also known as Postgres Functions) — These are written in SQL or PL/pgSQL and run inside your PostgreSQL database. They are executed close to the data layer and are ideal for performing data transformations, validations, and other operations tightly coupled to your database logic.

  2. Edge Functions — These are written in TypeScript using the Deno runtime. They are deployed globally and run in Supabase's serverless infrastructure. Edge Functions are designed for handling HTTP requests, integrating with third-party APIs, and performing operations that fall outside the scope of what you would typically want your database to handle.

Choosing between these two depends on your application’s requirements. Do you need low-latency, data-level operations? Or do you need to call out to a third-party API, send an email, or expose a custom API endpoint?

2. Database Functions in Supabase

What Are Database Functions?

Database Functions in Supabase are PostgreSQL functions that run inside the database engine. Since they are native to Postgres, they offer extremely low-latency execution and are excellent for any logic that directly involves your data tables.

You can create these functions using the SQL Editor in the Supabase dashboard or by including them in your migration files for better version control.

How to Create a Database Function

Here’s an example where we automatically assign a manager to a newly inserted listing. This logic would typically be used to enforce business rules like load-balancing between available managers.

create or replace function assign_manager()
returns trigger as $$
begin
  update listings
  set manager_id = (
    select id from user_profiles
    where role = 'manager'
    order by random()
    limit 1
  )
  where id = new.id;
  return new;
end;
$$ language

You would then attach this function to a trigger:

create trigger auto_assign_manager
after insert on listings
for each row
execute function assign_manager()

How to Access a Database Function via RPC (HTTP)

Once you've created a Database Function in Supabase (especially one that returns a result), Supabase automatically exposes it through its PostgREST API layer. This means you can call it from any frontend or backend client using either the Supabase client SDK or a direct HTTP request.

Using the Supabase Client (JS/TS)

const { data, error } = await supabase
  .rpc('get_recommended_locations', { budget: 1500 });

This method handles authentication and formatting internally, making it the easiest way to call your SQL functions from JavaScript or frontend tools like WeWeb or FlutterFlow (via plugins).

Calling via HTTP Endpoint (RPC REST API)

Supabase also allows calling database functions directly via HTTP using the /rest/v1/rpc/ route. Here's how you do it with curl:

curl -X POST 'https://<your-project>.supabase.co/rest/v1/rpc/get_recommended_locations' \
  -H "Content-Type: application/json" \
  -H "apikey: YOUR_SUPABASE_ANON_OR_SERVICE_ROLE_KEY" \
  -H "Authorization: Bearer YOUR_SUPABASE_JWT" \
  -d '{ "budget": 1500 }'

While this is a valid HTTP call, keep in mind:

  • It always uses the POST method, even for data fetching.

  • You must format your d payload as JSON matching the function parameters.

  • Custom headers or flexible routing are not supported — this is strictly tied to the database structure.


When Should You Use Database Functions?

Database Functions are well-suited for the following scenarios:

  • Automatically assigning or calculating values during inserts or updates

  • Validating data before writing it to the database

  • Transforming or enriching records as part of a trigger

  • Centralizing business logic that must always run on the database side

  • Running complex calculations or filtering logic that benefits from running close to the data

3. Edge Functions in Supabase

What Are Edge Functions?

Supabase Edge Functions are serverless functions written in TypeScript using the Deno runtime. They are deployed to Supabase’s globally distributed infrastructure, which enables low-latency responses anywhere in the world.

Unlike Database Functions, Edge Functions are designed to handle HTTP requests. They are ideal for custom backend logic that needs to be exposed to clients or integrated with third-party systems.

How to Create an Edge Function

Using the Supabase CLI, you can create and deploy an Edge Function with a few simple commands.

This creates a directory under supabase/functions/send-tour-email.

Here is an example of a basic function that sends an email when a user books a tour:

// supabase/functions/send-tour-email/index.ts
import { serve } from "<https://deno.land/std/http/server.ts>";

serve(async (req) => {
  const { email, tour_id } = await req.json();

  // Here you might send an email using a third-party service like Resend, Mailgun, etc.
  console.log(`Sending confirmation to ${email} for tour ID ${tour_id}`);

  return new Response(`Email sent to ${email}`, { status: 200 });
});

Deploy the function using:

After deployment, the function is accessible via a public URL:

https://<your-project-ref>

When Should You Use Edge Functions?

Edge Functions are an excellent choice for use cases that involve:

  • Creating secure custom API endpoints

  • Consuming or responding to third-party webhooks (e.g., Stripe, Slack)

  • Performing server-side logic that cannot run inside the database (e.g., fetching external APIs, sending emails)

  • Background tasks such as PDF generation, analytics tracking, or processing user-uploaded files

  • Scheduled jobs (using GitHub Actions or external schedulers to call the functions on a cron schedule)

4. Choosing Between Database Functions and Edge Functions

Here’s a simplified comparison to help you decide which type of function to use based on your use case:

Feature / Use Case

Database Function (SQL)

Edge Function (TypeScript)

Runs inside database

Yes

No

Can be triggered by table events

Yes

No

Can call external APIs

Difficult

Yes

Low-latency execution

Very fast (internal)

Fast (network-dependent)

Exposed as HTTP endpoint

Yes

(via Supabase’s auto-generated RPC endpoint — POST /rest/v1/rpc/<function>)

Yes

(deployed as a fully customisation HTTP endpoint — supports GET, POST, custom paths, and headers)

Integrates with frontend apps

Yes

(can be called via HTTP or client SDK, but limited to JSON format and POST only)

Yes

(full HTTP control — headers, query params, custom routes — ideal for frontend or external API use)

Best for

Data transformation, validation, enforcement

APIs, external integration, background jobs

A good rule of thumb: use Database Functions for anything that strictly involves data manipulation within your database. Use Edge Functions when you need to step outside of the database — whether it’s sending an email, processing a file, or communicating with another service.

5. Real-World Use Case Examples

Normalizing Survey Responses with a Database Function

You might receive raw JSON responses from a frontend survey tool. To ensure data consistency, you can use a Database Function to normalize the structure before storing it:

create or replace function normalize_response(response json)
returns json as $$
begin
  -- Apply normalization logic
  return response; -- Example: sanitized or restructured version
end;
$$ language

This function can then be used in an insert trigger or even called manually during an ETL (extract-transform-load) process.

Sending a Welcome Email on Client Registration with an Edge Function

Here’s a case where a new client signs up and you want to send a welcome email. You could trigger an Edge Function from your frontend:

const res = await fetch('https://<project-ref>.functions.supabase.co/send-welcome', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ email: 'client@example.com' }),
});

The Edge Function might then send the email, log the signup in a Slack channel, and return a success message to the frontend.

6. Performance Considerations

When it comes to performance, both function types are optimized for their respective domains, but there are differences.

  • Database Functions are incredibly fast because they are executed inside the database engine. There is no network overhead, and operations are optimized at the SQL level.

  • Edge Functions are also fast due to their serverless edge deployment, but they involve network hops and startup time (albeit minimal due to Deno’s low cold start times).

You should avoid pulling data from the database into an Edge Function just to perform a transformation that could have been done using SQL or a Database Function. This helps reduce latency and unnecessary traffic between layers.

7. Best Practices and Common Pitfalls

  • Keep your functions modular and small. Whether you're using SQL or TypeScript, separating concerns improves maintainability.

  • For Edge Functions, avoid heavy startup dependencies. The Deno runtime is fast, but bloated functions will incur cold start delays.

  • Use environment variables for secure credentials in Edge Functions — don’t hardcode API keys or tokens.

  • Monitor your function logs and usage through the Supabase dashboard or CLI tools to avoid hitting rate limits, especially on the free tier.

  • Combine function types when needed. For example, you can have an Edge Function call a Database Function if both forms of logic are necessary for a complete workflow.

8. Conclusion

Supabase Functions allow you to move beyond treating Supabase as just a database. With Database Functions, you can embed business logic right at the data layer. With Edge Functions, you can build modern, serverless APIs that extend your application’s capabilities to external services.

To summarize:

  • Use Database Functions for data-centric operations, validation, and triggers.

  • Use Edge Functions for HTTP APIs, third-party integrations, and background tasks.

  • Don’t hesitate to mix both in a single workflow for maximum flexibility.

Understanding when and how to use these tools is key to building performant and scalable Supabase-powered applications. Once you do, you’ll find that you rarely need to reach for a traditional backend framework.

FAQ

Q1: Can I call a Database Function from an Edge Function?

A: Yes, you can call a PostgreSQL database function from a Supabase Edge Function. Use the Supabase client library within your Edge Function to make a request to the database.

Q2: Do Edge Functions support Python?

A: No, Supabase Edge Functions currently support only TypeScript/JavaScript using the Deno runtime. Python is not supported. All function logic should be written using Deno-compatible TypeScript, following Supabase's .

SHARE