🎉 Native Google & Apple sign-in is here → read the guide
Edge Functions

Edge Functions

Edge Functions are small pieces of server-side code (written in TypeScript and run on Deno) that you deploy to Supabase and call by name. Reach for one whenever logic has to run on a trusted server you control rather than inside the app — calling a paid API with a secret key, sending email, or charging a card. “Edge” means each function runs in many regions close to your users, so calls stay fast.

The supabase-functions module is the Kotlin side of that: it invokes a function by name, sends a request body, and parses the JSON it sends back into your own Kotlin types. You start, as always, by building a feature client from your SupabaseClient.

val functions = createFunctionsClient(client)

Typed invoke

A typed invoke means you send and receive your own @Serializable data classes instead of hand-writing raw JSON strings. You describe the shape of the request and the response once, and the library handles the conversion both ways. The call returns a SupabaseResult, so you branch on success and failure exactly like every other call in the library — see Results & Errors.

@Serializable data class HelloRequest(val name: String)
@Serializable data class HelloResponse(val message: String)
 
val result: SupabaseResult<HelloResponse> =
    functions.invokeTyped<HelloRequest, HelloResponse>(
        functionName = "hello-world",
        request = HelloRequest(name = "Ada"),
    )
 
result.onSuccess { println(it.message) }

Variants

There are a few flavours of invoke depending on what you send and what you want back. Pick the row that matches your case:

MethodBodyReturns
invokeTyped<Req, Resp>(functionName, request, …)@Serializable ReqResp
invokeTyped<Resp>(functionName, body?, …)JSON String?Resp
invokeWithBodyTyped<Resp>(functionName, body, contentType, …)ByteArray (raw bytes)Resp
invokeUnit(functionName, body?, …)JSON String?Unit (fire-and-forget)
invoke(functionName, body?, headers, region?)JSON String?raw String

A couple of those terms are worth unpacking. Fire-and-forget (invokeUnit) means you call the function but don’t care about the response body — you only need to know it succeeded, as when triggering a background job. The plain invoke hands you the response as a raw String, which is useful when the function returns something that isn’t JSON, or when you’d rather parse it yourself.

Regions

By default Supabase picks a region for you. If a call is latency-sensitive you can pin it to a specific region so it always runs there:

functions.invokeTyped<HelloResponse>(
    functionName = "hello-world",
    region = FunctionRegion.US_EAST_1,
)

FunctionRegion covers every Supabase edge region: ANY (let Supabase choose), US_EAST_1, US_WEST_1, US_WEST_2, CA_CENTRAL_1, SA_EAST_1, EU_WEST_1, EU_WEST_2, EU_WEST_3, EU_CENTRAL_1, AP_SOUTH_1, AP_SOUTHEAST_1, AP_SOUTHEAST_2, AP_NORTHEAST_1, AP_NORTHEAST_2. Leaving region unset (or using ANY) lets Supabase route to the nearest healthy region.

Every invoke accepts a headers: Map<String, String> — handy for forwarding a user’s access token so the function runs under their RLS context. RLS context means the function executes as the signed-in user, so your Row Level Security rules apply to whatever it reads or writes on their behalf.