Recently I came across a Supabase method called .maybeSingle().
How is it different from .single()?
Let’s find out.
Below I have a function called doesUserExist() that queries a users table to find out whether a user by the given email ID exists:
import "server-only"
import { createClient } from "@/supabase/server"
export async function doesUserExist(email: string) {
const supabase = await createClient()
try {
const response = await supabase
.from("users")
.select("id, email")
.eq("email", email)
.single()
console.log(response)
} catch (error) {
console.log("Unexpected error: ", error)
}
}If I call this function with an email ID that doesn’t exist, the response object looks like this:

The data is null (as expected), and there is an error object. The status code is 406.
Now let’s replace .single() with .maybeSingle():
import "server-only"
import { createClient } from "@/supabase/server"
export async function doesUserExist(email: string) {
const supabase = await createClient()
try {
const response = await supabase
.from("users")
.select("id, email")
.eq("email", email)
.maybeSingle()
console.log(response)
} catch (error) {
console.log("Unexpected error: ", error)
}
}If I call this function, the response object looks like this:

The data is null and the error is null as well. The status code is 200.
You might ask: When should I use .single() versus .maybeSingle()?
Use .single() when your logic requires that the query must return exactly one record. This is useful for scenarios where missing data indicates a problem.
Use .maybeSingle() when it’s acceptable for the query to return no record (i.e., you expect zero or one row).
In our case, where we’re checking whether a user exists or not, .maybeSingle() would be more appropriate because a user not existing is an expected possibility, not an error condition.
