---
title: "Manage UDFs"
description: "Register and manage Lua User-Defined Functions (UDFs) on an Aerospike cluster using the Java and Python Developer SDKs."
---

# Manage UDFs

> For the complete documentation index see: [llms.txt](https://aerospike.com/docs/llms.txt)
> 
> All documentation pages available in markdown.

## Applies to

-   Aerospike Developer SDK preview (Java 21+ and Python 3.10+)
-   Aerospike Database 6.0 or later unless a section states otherwise

::: code examples
Examples assume a connected `session` from [Connect to Aerospike](https://aerospike.com/docs/develop/client/sdk/connect). Each usage guide lists shared imports in a tabbed block near the top of the page; snippet blocks add imports only for types not already shown. The first code block in each section includes dataset setup; later blocks in that section reuse those values. When a page includes a **Complete example** section, that block is fully self-contained.
:::

User-Defined Functions (UDFs) are Lua modules that run inside the Aerospike server process. Register modules on the cluster before invoking them from a session.

::: server requirements
Aerospike Database 6.0 or later is required for UDF registration and removal. The Developer SDK preview supports record UDFs only; stream (aggregation) UDFs are not supported. For batch UDF invocation, server 6.0 or later is also required. See [Apply a UDF](https://aerospike.com/docs/develop/client/sdk/usage/udf/apply).
:::

Except where noted, snippets on this page use the imports below. A snippet lists additional `import` lines only when it needs a type not shown here. When this page includes a **Complete example** section, that block is fully self-contained with every import required to run it.

-   [Java](#tab-panel-3609)
-   [Python](#tab-panel-3610)

```java
import com.aerospike.client.sdk.Cluster;

import com.aerospike.client.sdk.ClusterDefinition;

import com.aerospike.client.sdk.Session;

import com.aerospike.client.sdk.policy.Behavior;

import com.aerospike.client.sdk.task.RegisterTask;
```

::: java: register on session
UDF admin APIs (`registerUdf`, `registerUdfString`, `removeUdf`) are on [`Session`](https://aerospike.com/docs/develop/client/sdk/connect), not on `Cluster`. Create a session from a connected cluster before registering modules.
:::

```python
from aerospike_sdk import Client
```

::: python: register on client
UDF admin APIs (`register_udf`, `register_udf_from_file`, `remove_udf`) are exposed by [`Client`](https://aerospike.com/docs/develop/client/sdk/connect). Open a connected client before registering modules or creating a session.
:::

## Register from a file

`registerUdf` (Java) and `register_udf_from_file` (Python) take two path strings:

1.  Local file path: absolute path to the `.lua` source on your application host (for example `/tmp/example.lua` in the Python example, or the temp file path in the Java example). The SDK reads this file from disk before uploading it.
2.  Server module name: filename under each node’s `mod-lua` user path (for example `example.lua`). This is what Aerospike stores on the cluster, not a path on your machine.

Pass the module name without the `.lua` extension to `executeUdf().function()` (Java) or `execute_udf().function()` (Python) later.

-   [Java](#tab-panel-3611)
-   [Python](#tab-panel-3612)

```java
String exampleLua = """

    function readBin(r, name)

        return r[name]

    end

    function multiplyAndAdd(r, a, b)

        return r['factor'] * a + b

    end

    """;

try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) {

    Session session = cluster.createSession(Behavior.DEFAULT);

    // Write the module locally, then register it on the cluster

    java.nio.file.Path temp = java.nio.file.Files.createTempFile("example", ".lua");

    java.nio.file.Files.writeString(temp, exampleLua);

    RegisterTask task = session.registerUdf(temp.toAbsolutePath().toString(), "example.lua");

    task.waitTillComplete();

    // Module is available as package name "example" (no .lua suffix)

}
```

> 📖 **API reference**: [`Session.registerUdf`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Session.html#registerUdf%28java.lang.String%2Cjava.lang.String%29) | [`RegisterTask.waitTillComplete`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/task/RegisterTask.html#waitTillComplete%28%29)

```python
EXAMPLE_LUA = """\

function readBin(r, name)

    return r[name]

end

function multiplyAndAdd(r, a, b)

    return r['factor'] * a + b

end

"""

async with Client("localhost:3000") as client:

    # Write the module locally, then register it on the cluster

    with open("/tmp/example.lua", "w", encoding="utf-8") as f:

        f.write(EXAMPLE_LUA)

    task = await client.register_udf_from_file("/tmp/example.lua", "example.lua")

    await task.wait_till_complete()

    # Module is available as package name "example" (no .lua suffix)
```

> 📖 **API reference**: [`Client.register_udf_from_file`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/client.html#aerospike_sdk.aio.client.Client.register_udf_from_file) | [`RegisterTask.wait_till_complete`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/register-task.html)

Registration is asynchronous on the server. The client returns a `RegisterTask` immediately. Call `waitTillComplete()` (Java) or `await wait_till_complete()` (Python) before invoking the UDF so every node has the module.

## Register from an inline string

Use an in-memory Lua source when the module is built in your application or read from a config service. The `writeUnique` example below registers a separate module (`unique.lua`) so it does not overwrite `example.lua` from [Register from a file](#register-from-a-file).

-   [Java](#tab-panel-3613)
-   [Python](#tab-panel-3614)

```java
String uniqueLua = """

    -- Set a particular bin only if the record does not already exist.

    function writeUnique(r, name, value)

        if not aerospike:exists(r) then

            aerospike:create(r)

            r[name] = value

            aerospike:update(r)

        end

    end

    """;

try (Cluster cluster = new ClusterDefinition("localhost", 3000).connect()) {

    Session session = cluster.createSession(Behavior.DEFAULT);

    RegisterTask task = session.registerUdfString(uniqueLua, "unique.lua");

    task.waitTillComplete();

    // Module is available as package name "unique"

}
```

> 📖 **API reference**: [`Session.registerUdfString`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Session.html#registerUdfString%28java.lang.String%2Cjava.lang.String%29)

```python
UNIQUE_LUA = b"""\

-- Set a particular bin only if the record does not already exist.

function writeUnique(r, name, value)

    if not aerospike:exists(r) then

        aerospike:create(r)

        r[name] = value

        aerospike:update(r)

    end

end

"""

async with Client("localhost:3000") as client:

    task = await client.register_udf(UNIQUE_LUA, "unique.lua")

    await task.wait_till_complete()

    # Module is available as package name "unique"
```

> 📖 **API reference**: [`Client.register_udf`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/client.html#aerospike_sdk.aio.client.Client.register_udf)

::: server module path
Registered modules are stored under each node’s `mod-lua` `user-path` in `aerospike.conf`. Pass the server filename when registering (for example `example.lua` or `unique.lua`). In `.function()`, use the package name without the `.lua` suffix (`example`, `unique`).
:::

## Remove a registered module

-   [Java](#tab-panel-3615)
-   [Python](#tab-panel-3616)

```java
session.removeUdf("example.lua");
```

> 📖 **API reference**: [`Session.removeUdf`](https://javadoc.io/doc/com.aerospike/aerospike-client-sdk/latest/com/aerospike/client/sdk/Session.html#removeUdf%28java.lang.String%29)

```python
task = await client.remove_udf("example.lua")

await task.wait_till_complete()
```

> 📖 **API reference**: [`Client.remove_udf`](https://aerospike-python-sdk.readthedocs.io/en/latest/api/client.html#aerospike_sdk.aio.client.Client.remove_udf)