BaaS Service User Guide
This topic describes how to use BaaS Service (Supabase Compatible), including obtaining API credentials, performing data operations with language-specific SDKs, deploying Edge Functions, and leveraging AI-assisted development.
Obtain the Supabase URL and API key
Before using the Supabase SDK or calling the API, you must obtain the Supabase URL and API key for your service.
Supabase URL
The Supabase URL is the entry point of the API gateway. All client requests access the BaaS Service through this URL. URL format: <supabase_instance_ID>.polardbxaisupabase.rds.aliyuncs.com
API key types
Supabase provides two types of API keys for different scenarios:
|
Key type |
Use case |
Description |
|
anonKey |
Frontend / Client |
Restricted by Row Level Security (RLS) policies. Can only access data permitted by RLS policies. Safe to expose in client-side code. |
|
serviceRoleKey |
Backend / Server |
Bypasses all RLS policies and has full data access. Use only in trusted server-side environments. |
Do not expose serviceRoleKey in frontend code. This key bypasses all Row Level Security policies, and a leak would allow unauthorized data access. Use it only in backend services and manage it through environment variables.
JWT Payload structure
API keys are essentially JWTs (JSON Web Tokens). Different key types contain different payloads. The following examples show the payload for each type:
-
anon key Payload
{ "iss": "supabase", "ref": "your-project-ref", "role": "anon", "iat": 1700000000, "exp": 2000000000 } -
service_role key Payload
{ "iss": "supabase", "ref": "your-project-ref", "role": "service_role", "iat": 1700000000, "exp": 2000000000 } -
Authenticated user Payload
{ "aud": "authenticated", "exp": 1700003600, "iat": 1700000000, "iss": "https://your-project-ref.supabase.co/auth/v1", "sub": "user-uuid-here", "email": "user@example.com", "role": "authenticated", "session_id": "session-uuid-here" }
SDK usage
Supabase provides official SDKs for multiple languages, supporting database CRUD operations, user authentication, real-time subscriptions, file uploads, and more. Select your development language to view the integration method.
Note on table creation: Create and manage table schemas through the Dashboard using the Table Editor (visual) or SQL Editor. SDKs are used only for data read/write operations.
JavaScript / TypeScript
-
Installation
npm install @supabase/supabase-js -
Initialization and data operations
import { createClient } from '@supabase/supabase-js' const supabase = createClient( '<YOUR_SUPABASE_URL>', '<YOUR_SUPABASE_ANON_KEY>' ) // Sign up const { data: { user } } = await supabase.auth.signUp({ email: 'user@example.com', password: 'password123' }) // Sign in const { data: { session } } = await supabase.auth.signInWithPassword({ email: 'user@example.com', password: 'password123' }) // Insert data const { data } = await supabase.from('todos').insert({ title: 'Learn Supabase', done: false }).select() // Query data const { data: todos } = await supabase.from('todos') .select('*') .eq('done', false) .order('created_at', { ascending: false }) // Update data const { data: updated } = await supabase.from('todos') .update({ done: true }) .eq('id', 1) .select() // Delete data await supabase.from('todos').delete().eq('id', 1) // Real-time subscription supabase.channel('todos-changes') .on('postgres_changes', { event: '*', schema: 'public', table: 'todos' }, (payload) => { console.log('Data changed:', payload) }) .subscribe() // File upload await supabase.storage.from('avatars').upload('user1/avatar.png', file)
Python
-
Installation
pip install supabase -
Initialization and data operations
import os from supabase import create_client, Client url: str = os.environ.get("YOUR_SUPABASE_URL") key: str = os.environ.get("YOUR_SUPABASE_ANON_KEY") supabase: Client = create_client(url, key) # Sign up res = supabase.auth.sign_up({"email": "user@example.com", "password": "password123"}) # Sign in res = supabase.auth.sign_in_with_password({"email": "user@example.com", "password": "password123"}) # Insert supabase.table("todos").insert({"title": "Learn Supabase", "done": False}).execute() # Query response = supabase.table("todos").select("*").eq("done", False).order("created_at", desc=True).execute() # Update supabase.table("todos").update({"done": True}).eq("id", 1).execute() # Delete supabase.table("todos").delete().eq("id", 1).execute() # File upload supabase.storage.from_("avatars").upload("user1/avatar.png", file_data)
Flutter / Dart
-
Installation
flutter pub add supabase_flutter -
Initialization and data operations
import 'package:supabase_flutter/supabase_flutter.dart'; Future<void> main() async { await Supabase.initialize( url: '<YOUR_SUPABASE_URL>', anonKey: '<YOUR_SUPABASE_ANON_KEY>', ); runApp(MyApp()); } final supabase = Supabase.instance.client; // Sign up await supabase.auth.signUp(email: 'user@example.com', password: 'password123'); // Sign in await supabase.auth.signInWithPassword(email: 'user@example.com', password: 'password123'); // Insert await supabase.from('todos').insert({'title': 'New task', 'done': false}); // Query final data = await supabase.from('todos').select().eq('done', false).order('created_at'); // Update await supabase.from('todos').update({'done': true}).eq('id', 1); // Delete await supabase.from('todos').delete().eq('id', 1); // File upload await supabase.storage.from('avatars').upload('user1/avatar.png', file);
Swift
Initialization and data operations
import Supabase
let client = SupabaseClient(
supabaseURL: URL(string: "<YOUR_SUPABASE_URL>")!,
supabaseKey: "<YOUR_SUPABASE_ANON_KEY>"
)
// Sign up
try await client.auth.signUp(email: "user@example.com", password: "password123")
// Sign in
try await client.auth.signIn(email: "user@example.com", password: "password123")
// Insert
try await client.from("todos").insert(["title": "New task", "done": false]).execute()
// Query
let todos: [Todo] = try await client.from("todos").select().eq("done", value: false).execute().value
// Update
try await client.from("todos").update(["done": true]).eq("id", value: 1).execute()
// Delete
try await client.from("todos").delete().eq("id", value: 1).execute()
Kotlin
Initialization and data operations
val supabase = createSupabaseClient(
supabaseUrl = "<YOUR_SUPABASE_URL>",
supabaseKey = "<YOUR_SUPABASE_ANON_KEY>"
) {
install(Auth)
install(Postgrest)
install(Storage)
}
// Sign up
supabase.auth.signUpWith(Email) { email = "user@example.com"; password = "password123" }
// Sign in
supabase.auth.signInWith(Email) { email = "user@example.com"; password = "password123" }
// Insert
supabase.from("todos").insert(Todo(title = "New task", done = false))
// Query
val todos = supabase.from("todos").select { filter { eq("done", false) } }.decodeList<Todo>()
// Update
supabase.from("todos").update({ set("done", true) }) { filter { eq("id", 1) } }
// Delete
supabase.from("todos").delete { filter { eq("id", 1) } }
C#
Initialization and data operations
var url = Environment.GetEnvironmentVariable("YOUR_SUPABASE_URL") ?? throw new InvalidOperationException("Environment variable YOUR_SUPABASE_URL is not set.");
var key = Environment.GetEnvironmentVariable("YOUR_SUPABASE_ANON_KEY") ?? throw new InvalidOperationException("Environment variable YOUR_SUPABASE_ANON_KEY is not set.");
var supabase = new Supabase.Client(url, key);
await supabase.InitializeAsync();
// Sign up
await supabase.Auth.SignUp("user@example.com", "password123");
// Sign in
await supabase.Auth.SignIn("user@example.com", "password123");
// Insert
await supabase.From<Todo>().Insert(new Todo { Title = "New task", Done = false });
// Query
var todos = await supabase.From<Todo>().Filter("done", Operator.Equals, "false").Get();
// Update
await supabase.From<Todo>().Filter("id", Operator.Equals, "1").Update(new Todo { Done = true });
// Delete
await supabase.From<Todo>().Filter("id", Operator.Equals, "1").Delete();
Edge Functions
Edge Functions are serverless functions that run on the Supabase platform, powered by the Deno runtime with TypeScript support. You can use Edge Functions to implement custom business logic, third-party API integrations, webhook handling, and more.
Create a function
Create a TypeScript file as the function entry point. The following example implements a simple Hello World function:
// supabase/functions/hello-world/index.ts
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
Deno.serve(async (req: Request) => {
const { name } = await req.json()
const data = {
message: `Hello ${name}!`,
}
return new Response(
JSON.stringify(data),
{ headers: { "Content-Type": "application/json" } }
)
})
Deploy a function
Deploy Edge Functions through the API:
curl -X POST "https://<YOUR_SUPABASE_URL>/functions/v1/deploy" \
-H "Authorization: Bearer <YOUR_SUPABASE_SERVICE_KEY>" \
-H "Content-Type: application/json" \
-d '{
"slug": "hello-world",
"name": "hello-world",
"entrypoint_path": "./index.ts",
"verify_jwt": true
}'
Deployment parameter description:
|
Parameter |
Type |
Description |
|
|
STRING |
The URL path identifier of the function, used for URL construction when invoking the function. |
|
|
STRING |
The display name of the function. |
|
|
STRING |
The relative path to the function entry file. |
|
|
BOOLEAN |
Whether to verify the JWT token in requests. When set to |
Invoke a function
After deployment, invoke the Edge Function with an HTTP POST request:
curl -X POST "https://<YOUR_SUPABASE_URL>/functions/v1/hello-world" \
-H "Authorization: Bearer <YOUR_SUPABASE_ANON_KEY>" \
-H "Content-Type: application/json" \
-d '{"name": "World"}'
Manage functions
-
List functions
curl -X GET "https://<YOUR_SUPABASE_URL>/functions/v1/" \ -H "Authorization: Bearer <YOUR_SUPABASE_SERVICE_KEY>" -
Update a function
curl -X PUT "https://<YOUR_SUPABASE_URL>/functions/v1/hello-world" \ -H "Authorization: Bearer <YOUR_SUPABASE_SERVICE_KEY>" \ -H "Content-Type: application/json" \ -d '{ "entrypoint_path": "./index.ts", "verify_jwt": false }' -
Delete a function
curl -X DELETE "https://<YOUR_SUPABASE_URL>/functions/v1/hello-world" \ -H "Authorization: Bearer <YOUR_SUPABASE_SERVICE_KEY>"
Use the SDK in functions
You can initialize a Supabase client inside Edge Functions and use the SDK to interact with the database. This approach automatically enforces RLS policies.
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2"
Deno.serve(async (req: Request) => {
const supabase = createClient(
Deno.env.get("<YOUR_SUPABASE_URL>") ?? "",
Deno.env.get("<YOUR_SUPABASE_ANON_KEY>") ?? "",
{
global: {
headers: { Authorization: req.headers.get("Authorization")! }
}
}
)
const { data, error } = await supabase
.from("todos")
.select("*")
return new Response(
JSON.stringify({ data, error }),
{ headers: { "Content-Type": "application/json" } }
)
})
Connect directly to the PolarDB-X database
In Edge Functions, you can also use mysql2/promise to connect directly to the PolarDB-X database and execute raw SQL.
import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import mysql from "npm:mysql2/promise"
Deno.serve(async (req: Request) => {
const connection = await mysql.createConnection({
host: Deno.env.get("DB_HOST"),
port: Number(Deno.env.get("DB_PORT") || 3306),
user: Deno.env.get("DB_USER"),
password: Deno.env.get("DB_PASSWORD"),
database: Deno.env.get("DB_NAME"),
})
try {
const [rows] = await connection.execute("SELECT * FROM todos WHERE completed = ?", [false])
return new Response(
JSON.stringify({ data: rows }),
{ headers: { "Content-Type": "application/json" } }
)
} finally {
await connection.end()
}
})
When you access the database through the SDK, RLS policies are automatically enforced. When you connect directly to the database, all RLS policies are bypassed. Choose the appropriate access method based on your security requirements.
AI-assisted development
To improve development efficiency, we recommend loading the mysql-supabase-dev skill pack in your AI coding tool. This skill pack is optimized for BaaS Service (Supabase Compatible) scenarios and covers the following use cases:
-
SDK usage: Automatically generates SDK call code following best practices, including error handling and type definitions.
-
RLS policy authoring: Automatically generates Row Level Security policy SQL statements based on your business requirements.
-
SQL syntax mapping: Automatically maps PostgreSQL syntax to MySQL-compatible syntax for the PolarDB-X engine.
-
Edge Functions development: Assists with writing, debugging, and deploying Edge Functions.
-
Database migration scripts: Automatically generates migration files for schema changes.
Supported AI coding tools: Claude, Cursor, Codex, and Qoder.
Learn more
For more Supabase features and advanced usage, see the official Supabase documentation: Supabase official documentation