Chapter 12 · APOC, Procedures, Functions, Triggers-Like Workflows, and Extending Cypher

Custom Procedures/Functions Concepts, Java Extension Boundaries, Version Compatibility, and Deployment Risk

Treat custom Java procedures/functions as server deployment artifacts with compatibility, security, memory, test and rollback obligations—not merely alternate query syntax.

Advanced165–210 minutesCustom extension boundary labNeo4j 2026.07.1 Community · Cypher 25APOC Core 2026.07.1 optionalLast reviewed: September 2026

Learning outcomes

AtlasMart proposes a custom Java procedure because a transformation is “too slow in Cypher.” That may be valid, but a server-side JAR runs inside the Neo4j process and becomes part of the database deployment. The correct threshold is therefore much higher than “the code is easier to write in Java.”

01

Explain the API and lifecycle boundary of a custom procedure versus user-defined function.

02

Pin custom extension compilation/testing to the exact Neo4j server line.

03

Use Neo4j Harness and driver tests before deploying a JAR to a real server.

04

Identify heap, privilege, compatibility and observability risks of server-side Java code.

05

Compare a trigger/custom-procedure approach with pure Cypher and application services before deployment.

Chapter 12 baseline · reviewed 9 September 2026

The mandatory lab continues Neo4j Community 2026.07.1, database neo4j, explicit CYPHER 25 for version-sensitive examples, container atlasmart-neo4j, authentication enabled, loopback HTTP/Bolt endpoints, and the AtlasMart identifiers/model built in Chapters 01–11. Neo4j 5.26.30 remains the LTS comparison line. This chapter adds APOC Core 2026.07.1 as an optional extension; APOC Extended is never required.

Evidence and privilege note

This generation environment does not run the Neo4j container, so no plugin load, procedure list, filesystem read/write, HTTP request, trigger execution or custom-JAR output is invented. The lab tells you exactly what to inspect. Community Edition lacks Enterprise RBAC/load privileges, so the free path emphasizes configuration minimization, loopback-only access, file/network denial by default, and application-level authorization boundaries.

1. Custom extensions run in the database JVM

Extension Call shape Good fit Risk
User-defined function Expression returning a value Pure deterministic computation that composes in Cypher Bad implementation can consume CPU/heap in query execution
User-defined procedure CALL yielding rows/performing permitted work Specialized server-side operation with clear transactional semantics Row cardinality, writes, privileges and exception behavior become API contract
Unmanaged server extension HTTP/JAX-RS surface Rare cases needing custom HTTP integration on self-managed server Sharp tool: arbitrary server code, heap/security surface, tight deployment coupling
Application service Driver calls over Bolt Business orchestration, external I/O, independent deployment Network round trips and separate service operations

Neo4j’s Java Reference explicitly treats these as advanced server/deployment mechanisms, not driver-side extensions.

2. Compile against the same release line

Maven · key dependency pins for the current lab
<properties>  <maven.compiler.release>21</maven.compiler.release>  <neo4j.version>2026.07.1</neo4j.version></properties><dependency>  <groupId>org.neo4j</groupId>  <artifactId>neo4j</artifactId>  <version>${neo4j.version}</version>  <scope>provided</scope></dependency><dependency>  <groupId>org.neo4j.test</groupId>  <artifactId>neo4j-harness</artifactId>  <version>${neo4j.version}</version>  <scope>test</scope></dependency>

The official current project template uses Neo4j 2026.07.1 and Java 21. Custom code should be rebuilt and regression-tested during server upgrades because it shares the server-side API/deployment lifecycle.

3. Minimal function: keep it pure and bounded

Java · illustrative function shape
package academy.atlasmart;import org.neo4j.procedure.Name;import org.neo4j.procedure.UserFunction;public class AtlasMartFunctions {    @UserFunction("atlasmart.normalizedSku")    public String normalizedSku(@Name("value") String value) {        if (value == null) return null;        return value.trim().toUpperCase().replaceAll("[^A-Z0-9-]", "");    }}

This example is intentionally small. Before deploying it, define Unicode/locale semantics and test malicious/large inputs. A custom function does not become safe merely because it does not write the graph.

4. Test in Harness before copying a JAR into plugins

Java · conceptual Harness regression test
try (Neo4j neo4j = Neo4jBuilders.newInProcessBuilder()        .withFunction(AtlasMartFunctions.class)        .build()) {    try (Driver driver = GraphDatabase.driver(neo4j.boltURI())) {        try (Session session = driver.session()) {            Record r = session.run(                "RETURN atlasmart.normalizedSku($v) AS sku",                Values.parameters("v", " sku-1001 ")            ).single();            assertEquals("SKU-1001", r.get("sku").asString());        }    }}

Test nulls, invalid inputs, large inputs, concurrency, exception mapping and Cypher 25 invocation. Then test the packaged JAR against a disposable server that matches production topology/configuration before rollout.

5. Deployment changes are database changes

Step Evidence
Build reproducibly Pinned Maven dependencies, checksum/SBOM and clean CI build
Security review No arbitrary file/network access; explicit privileges; dependency vulnerabilities reviewed
Compatibility test Harness + disposable Neo4j 2026.07.1 tests pass
Install JAR in $NEO4J_HOME/plugins; allowlist only required namespace
Restart Server startup log shows extension load without errors
Verify SHOW FUNCTIONS/PROCEDURES returns only intended names
Rollback Previous server/plugin pair and removal/restart procedure documented

6. Deliberately wrong: move application orchestration into a custom procedure

A custom procedure that calls payment APIs, sends email and writes files turns a database transaction into a distributed side-effect orchestrator. Client timeouts and transaction retries become dangerous, external dependencies can hold locks open, and observability is harder. Keep external I/O in application/workflow services; use Neo4j transactions for graph state and durable outbox facts.

7. Trigger compatibility and upgrade coupling

APOC trigger procedures are another form of server-side coupling. They are disabled by default via apoc.trigger.enabled=false. Current Cypher 25 uses apoc.trigger.install/drop/list; legacy apoc.trigger.add is removed in Cypher 25. Treat triggers as optional operational extensions, document every installed trigger, and include them in upgrade and rollback tests.

Cypher · inventory triggers only when enabled/authorized
CYPHER 25CALL apoc.trigger.list()YIELD name, query, selectorRETURN name, query, selectorORDER BY name;

Check your understanding

  1. Why should custom procedures be rebuilt/tested during Neo4j upgrades?
  2. What does Neo4j Harness provide?
  3. Should a custom procedure perform remote payment/email calls inside a graph transaction?
  4. Is apoc.trigger.add a Cypher 25 API to build new code on?
  5. What is the deployment rollback unit?
Review the answers

1. They run against server-side APIs and share the DBMS deployment/runtime lifecycle.

2. A lightweight Neo4j test instance for registering and testing procedures/functions before server deployment.

3. Usually no; external side effects should live in application/workflow services with idempotent coordination.

4. No. It is removed in Cypher 25; current trigger installation uses the newer procedures.

5. The tested server/plugin/configuration combination, not just one source file.

Summary and next step

Custom extensions are justified when a stable server-side capability clearly beats native Cypher/APOC/application alternatives and the team accepts the deployment burden. Lesson 5 turns that into a decision framework.

Authoritative references

Keep knowledge open

Help the academy stay free and grow.

If these tutorials save you time, a small donation supports new lessons, technical review, diagrams, examples, and long-term maintenance.

ETHEthereum / ERC-20 only
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0

Send only Ethereum or ERC-20 compatible assets to this address.