Writing and Deploying a Simple Aerospike Lua UDF for Counter Increment
Learn how to write, register, and invoke a simple Aerospike Lua UDF that increments a bin, plus size limits, runtime constraints, and verification steps.
11 Sept 2026, 19:32 UTC

Useful answer
To reduce round‑trips when you need to increment a numeric bin on every write, register a small Lua User‑Defined Function (UDF) that runs inside the Aerospike cluster and call it from your client. The UDF receives the bin name and the increment value, adds them, and returns the new value so the record is updated in a single server‑side operation.
Worked example
1. Write the Lua UDF
Create a file named counter_inc.lua with the following content. It uses only Lua 5.1 features and the Aerospike helper as.map (not needed for a simple scalar but shows the pattern).
-- counter_inc.lua
function inc(bin, val)
-- Ensure the incoming value is numeric; if not, treat it as 0
if type(val) ~= \"number\" then
val = 0
end
-- Read current bin value (nil if bin does not exist)
local cur = record[bin]
if type(cur) ~= \"number\" then
cur = 0
end
-- New value
local newv = cur + val
-- Write back
record[bin] = newv
return newv
end
2. Register the UDF with the cluster
Run the asadmin command on any node that has access to the cluster. You need the udf-admin privilege.
asadmin udf add counter_inc.lua
After registration, verify it appears in the list:
asadmin udf list
You should see counter_inc.lua among the entries.
3. Invoke the UDF from a client (Python example)
Assuming you have the Aerospike Python client installed, the call looks like this:
import aerospike
import aerospike.policy as policy
client = aerospike.Client({'hosts': [('127.0.0.1', 3000)]})
client.connect()
key = ('test', 'demo', 'user123') # (namespace, set, key)
bin_name = 'counter'
increment = 5
# Execute the UDF
result = client.execute(
None, # write policy – use defaults
key,
'counter_inc', # module name (file without .lua)
'inc', # function name
bin_name,
increment
)
print('UDF returned:', result) # should be the new counter value
# Optional: read the record to confirm persistence
(key, meta, record) = client.get(key)
print('Record bin:', record.get(bin_name))
client.close()
The execute call sends the key, module, function, and arguments to the server. The UDF runs on the node that owns the record, updates the bin, and returns the new value.
Limits and common mistakes
Size and runtime limits
- Each UDF source file must be ≤ 1 MB. Larger files are rejected during
asadmin udf add. - Aerospike only supports Lua 5.1. Syntax introduced in Lua 5.2/5.3 (e.g., bitwise operators,
goto) will cause a compilation error.
Memory and performance considerations
- UDF code is loaded into the JVM heap of each node. Very large UDFs increase heap pressure and can contribute to out‑of‑memory conditions, especially under heavy write loads.
- Keep functions stateless and avoid loops over large data structures; prefer Aerospike’s built‑in map/list helpers (
as.map,as.list) for bulk operations.
Version compatibility
- Major Aerospike upgrades may change the UDF engine. After an upgrade, re‑run
asadmin udf listto ensure your functions are still present and test them with a known dataset. - If you see
UDFerrors in/var/log/aerospike/aerospike.log, check the Lua version and any deprecated APIs.
Typical pitfalls
- Missing
recordtable: The UDF receives a globalrecordrepresenting the target record. Forgetting to index it (e.g., using a local variable) will cause the write to be ignored. - Incorrect argument order: The client
executecall must pass arguments in the same order as the function signature. SwappingbinNameandvalueleads to type errors or unexpected results. - Neglecting ACLs: UDFs run with the server process privileges. If you expose sensitive data or allow arbitrary Lua execution without proper ACLs, you risk privilege escalation. Restrict UDF execution to trusted roles via
role-admincommands. - Assuming atomicity across bins: A UDF that updates multiple bins is atomic only with respect to the record; concurrent UDFs on the same record are serialized by the server, but you should still design idempotent logic if retries are possible.
Practical verification steps
- After
asadmin udf add, runasadmin udf listand confirm the file name appears. - Execute the UDF via your client and capture the return value. Compare it to the expected
old_value + increment. - Read the record back with
client.getand verify the bin matches the returned value. - Inspect the Aerospike log for lines containing
UDFand the function name; successful execution logs at INFO level. - Run
asadmin cluster statusbefore and after a burst of UDF calls to ensure no node transitions toUNHEALTHYor shows risingheap_util_pctbeyond safe thresholds (typically < 80%).
0 replies
A thoughtful contribution can make all the difference. Be the first to share one.