Python UDFs
On this page
Note
This is a Preview feature.
A Python User-Defined Function (UDF) is an external function that allows you to execute Python code outside of the SingleStore engine's process.
Prerequisites
To enable Python UDFs in your SingleStore deployment, ensure the following:
-
SingleStore Version: SingleStore version 8.
9 or later. -
Environment: The SingleStore deployment must run in an AWS EKS IRSA-supported environment.
-
Engine Global Variable:
enable_
must be enabled.managed_ functions SET GLOBAL enable_managed_functions = 1;Once this engine variable is enabled, you can create and deploy Python UDFs and TVFs.
Publish a Python UDF
Create a Python UDF
Python UDFs can be created in Shared Notebook only.
-
In the left navigation, select Query Editor > Shared.
-
Select Publish (on the top right).
New Python UDF
After selecting Publish, a new dialog box appears.
Publish Settings
Publish as |
Select Python UDF. |
Name |
Enter a name of the Python UDF. |
Description |
Enter the Python UDF description. |
Notebook |
Select a shared notebook to publish as a Python UDF. |
Deployment |
Select the SingleStore deployment (workspace) your notebook will connect to. Selecting a workspace allows you to connect to your SingleStore databases referenced in the Notebook natively. |
Runtime |
Select runtime among:
|
Idle Timeout |
Select idle timeout. |
Select Next.
Select Publish to publish the notebook as Python UDF.
Manage an Existing Python UDF
You can view, update and delete Python UDFs in the Cloud Portal by navigating to Container Apps > Python UDFs.
View an Existing Python UDF
To view an existing Python UDF, select the Python UDF from the Name column.
View Live Logs
To view live logs of the selected Python UDF, select View Live Logs from the ellipsis on the right side.
Update an Existing Python UDF
To update an existing Python UDF, select the ellipsis in the Actions column of the Python UDF, and select Update.
Delete an Existing Python UDF
To delete an existing Python UDF, select the ellipsis in the Actions column of the Python UDF, and select Delete.
Defining Python UDFs
Each Python UDF must meet these requirements:
-
The function's parameters and return types must be annotated.
-
The function must be wrapped with the
@udf
decorator, which is located insinglestoredb.
.functions
The @udf
decorator is a critical component, as it automatically analyzes the type annotations to map Python data types to SingleStore data types.CREATE EXTERNAL FUNCTION
statement in the SingleStore database, ensuring a reliable connection between your Python code and your SQL queries.
There are two main types of Python UDFs, defined by the type annotations you use:
-
Scalar
-
Vectorized
Scalar Python UDFs
Scalar Python UDFs are defined with standard Python type annotations, such as int
, float
, or str
.
The following example demonstrates a scalar Python UDF:
from singlestoredb.functions import udfimport singlestoredb.apps as apps@udfasync def multiply(x: float, y: float) -> float:return x * y# Start Python UDF serverconnection_info = await apps.run_udf_app()print("UDF server running. Connection info:", connection_info)
This creates the following external function:
CREATE EXTERNAL FUNCTION multiply(x DOUBLE NOT NULL, y DOUBLE NOT NULL)RETURNS DOUBLE NOT NULLAS REMOTE SERVICE "http://<svchost>/<endpoint>/invoke" FORMAT ROWDAT_1;
Use async def
for improved cancellation handling.
Vectorized Python UDFs
Vectorized Python UDFs are defined with vector type annotations, such as numpy.
, pandas.
, polars.
, or pyarrow.
.
The following example demonstrates a vectorized Python UDF.
import numpy as npimport numpy.typing as nptfrom singlestoredb.functions import udf@udfasync def vec_multiply(x: npt.NDArray[np.float64],y: npt.NDArray[np.float64]) -> npt.NDArray[np.float64]:return x * y# Start Python UDF serverimport singlestoredb.apps as appsconnection_info = await apps.run_udf_app()
This creates the following external function:
CREATE EXTERNAL FUNCTION vec_multiply(x DOUBLE NOT NULL, y DOUBLE NOT NULL)RETURNS DOUBLE NOT NULLAS REMOTE SERVICE "http://<svchost>/<endpoint>/invoke" FORMAT ROWDAT_1;
Scalar Python TVFs
Scalar Python TVFs are defined in the same way as scalar Python UDFs, except that a scalar TVF uses a Table
annotation to indicate that the function returns a table.Table
object.
The following example demonstrates a scalar Python TVF:
import numpy as npimport numpy.typing as nptfrom singlestoredb.functions import udf, Table@udfdef async number_stats(n: npt.NDArray[np.int_],) -> Table[npt.NDArray[np.int_], npt.NDArray[np.int_], npt.NDArray[np.float64]]:numbers = np.arange(1, n[0] + 1, dtype=np.int_)squares = numbers ** 2roots = np.sqrt(numbers).round(2)return Table(numbers, squares, roots)# Start Python UDF serverimport singlestoredb.apps as appsconnection_info = await apps.run_udf_app()
This creates the following external function:
CREATE EXTERNAL FUNCTION`number_stats`(`n` BIGINT NOT NULL)RETURNS TABLE(`a` BIGINT NOT NULL)AS REMOTE SERVICE "http://<svchost>/<endpoint>/invoke" FORMAT ROWDAT_1;
SingleStore automatically generates generic column names if no names are associated with the return fields (a
in this example).
Vectorized Python TVFs
Vectorized Python TVFs operate in a way similar to vectorized Python UDFs.
The following example demonstrates a vectorized Python TVF:
import numpy as npimport numpy.typing as nptfrom singlestoredb.functions import udf, Table@udfdef vec_table_function(n: npt.NDArray[np.int_],) -> Table[npt.NDArray[np.int_], npt.NDArray[np.float64], npt.NDArray[np.str_]]:x = np.array([10] * n[0], dtype=np.int_)y = np.array([10.0] * n[0], dtype=np.float64)z = np.array(['ten'] * n[0], dtype=np.str_)# Returns a tuple of vectors (each column of the output)return Table(x, y, z)# Start Python UDF serverimport singlestoredb.apps as appsconnection_info = await apps.run_udf_app()
This creates the following external function:
CREATE EXTERNAL FUNCTION`vec_table_function`(`n` BIGINT NOT NULL)RETURNS TABLE(`a` BIGINT NOT NULL,`b` DOUBLE NOT NULL,`c` TEXT NOT NULL)AS REMOTE SERVICE "http://<svchost>/<endpoint>/invoke" FORMAT ROWDAT_1;
SingleStore automatically generates generic column names if no names are associated with the return fields (a
, b
, c
).
In this section
Last modified: September 18, 2025