APOC and the extension ecosystem

This section documents the current Neo4j 2026.x calendar-versioned line — Neo4j moved from semantic to calendar versioning (YYYY.MM) in 2025, and the same line applies to the Graph Data Science library — as published at the Neo4j documentation, which is the reference these pages are written and verified against. No specific monthly patch is pinned. Some areas (Aura’s internal infrastructure, the Raft consensus implementation details, and the GDS Pregel API’s low-level internals) are linked, not documented in depth.

This content was generated with the assistance of AI and should be verified against the official documentation before being relied on in production, as Neo4j iterates quickly.

This section’s bibliography lists the reference material consulted while preparing these pages.

APOC ("Awesome Procedures On Cypher") is the standard extension library for Neo4j — hundreds of procedures and functions covering refactoring, data import/export, graph algorithms, and utilities that plain Cypher does not expose. This page covers installing and locking it down, its most commonly used procedure families, and a brief pointer to the wider extension ecosystem beyond APOC itself.

Installing and allowlisting APOC

APOC ships as a separate .jar dropped into the server’s plugins directory (or pulled in automatically on Aura, where a curated subset is pre-installed). Because many APOC procedures can read/write the filesystem, call out to JDBC, or run arbitrary Cypher, a server does not expose them all by default: two settings in neo4j.conf control what is actually callable.

# neo4j.conf
# https://neo4j.com/docs/apoc/current/installation/

# Required for apoc.load.json / apoc.export.*.* to read and write files on disk
# instead of only remote URLs.
apoc.import.file.enabled=true
apoc.export.file.enabled=true

# Procedure/function allowlist: only names matching one of these globs are
# callable at all. Narrow this to the families a deployment actually needs
# rather than allowlisting the whole library.
dbms.security.procedures.allowlist=apoc.coll.*,apoc.load.*,apoc.refactor.*,apoc.periodic.*,apoc.export.*,apoc.path.*

# Procedures matching this pattern additionally run without Cypher's normal
# read/write permission checks -- keep this list at least as narrow as the
# allowlist above.
dbms.security.procedures.unrestricted=apoc.load.*,apoc.periodic.*

The server must be restarted after editing neo4j.conf. See APOC Installation for the plugin drop-in steps per deployment type and the full list of security settings, and APOC Introduction for how the library is organized into procedure/function families. The library itself is catalogued at the APOC documentation; its project home and release notes live at APOC on Neo4j Labs.

Refactoring procedures

apoc.refactor.* reshapes an already-loaded graph: merging duplicate nodes, and renaming labels, relationship types, or properties without a full reload.

// Two Person nodes for the same person (e.g. found via a dedup query);
// merge them into one, combining scalar properties into arrays where they differ.
MATCH (p1:Person {email: "ada@x.io"}), (p2:Person {email: "ada@x.io"})
WHERE id(p1) <> id(p2)
CALL apoc.refactor.mergeNodes([p1, p2], {properties: "combine", mergeRels: true})
YIELD node
RETURN node;

// Rename a label across the whole graph.
CALL apoc.refactor.rename.label("Person", "Customer") YIELD total RETURN total;

// Rename a relationship type.
CALL apoc.refactor.rename.type("ACTED_IN", "PERFORMED_IN") YIELD total RETURN total;

Loading JSON and JDBC data

apoc.load.json streams a JSON document or NDJSON feed (local file or URL) as one row per top-level value; apoc.load.jdbc runs a SQL query against any JDBC-reachable database and streams back one row per result row, both driving a downstream MERGE to build the graph.

// Load a JSON array of people and upsert them as nodes.
CALL apoc.load.json("https://example.com/data/people.json")
YIELD value
MERGE (p:Person {id: value.id})
SET p.name = value.name, p.email = value.email;

// Pull rows from a relational source via JDBC (driver jar must also be on the
// server's plugins/classpath) and upsert them.
CALL apoc.load.jdbc(
  "jdbc:postgresql://localhost:5432/mydb?user=neo4j&password=change-me",
  "SELECT id, name, email FROM customers"
)
YIELD row
MERGE (c:Customer {id: row.id})
SET c.name = row.name, c.email = row.email;

Path utility functions

The apoc.path.* family expands or filters paths with more control than a plain Cypher pattern — bounding by relationship type/direction, label, or level without hand-writing a variable-length pattern for every case.

// All nodes reachable within 2 hops via ACTED_IN in either direction.
MATCH (start:Person {name: "Keanu Reeves"})
CALL apoc.path.subgraphNodes(start, {
  relationshipFilter: "ACTED_IN>|<ACTED_IN",
  maxLevel: 2
})
YIELD node
RETURN node;

Periodic and batch processing

apoc.periodic.iterate splits a large update into batches, committing each one in its own transaction (optionally in parallel) so a bulk write on millions of rows does not hold one giant transaction open or blow the heap.

// Recompute a derived score for every unprocessed Person, 10k nodes per
// transaction, four batches running in parallel.
CALL apoc.periodic.iterate(
  "MATCH (p:Person) WHERE p.processed IS NULL RETURN p",
  "SET p.processed = true, p.score = size((p)-[:ACTED_IN]->())",
  {batchSize: 10000, parallel: true, concurrency: 4}
)
YIELD batches, total, timeTaken, errorMessages
RETURN batches, total, timeTaken, errorMessages;

Exporting data

apoc.export.csv. and apoc.export.json. write the result of a query, a set of nodes/relationships, or the whole database to a file (subject to apoc.export.file.enabled above) or return it inline as a stream.

// Export a query's results to CSV on the server's import directory.
CALL apoc.export.csv.query(
  "MATCH (p:Person)-[:ACTED_IN]->(m:Movie) RETURN p.name AS actor, m.title AS movie",
  "actors.csv",
  {}
);

// Export the entire database as JSON, one line per node/relationship.
CALL apoc.export.json.all("full-export.json", {});

The wider extension ecosystem

APOC is the general-purpose toolbox; a few other officially maintained projects extend Neo4j in more specific directions and are worth knowing about even though they are out of scope for this page:

  • The Neo4j GraphQL Library generates a GraphQL API (queries, mutations, and subscriptions) directly from a GraphQL type-definitions schema, translating each request into Cypher — Neo4j GraphQL Library.

  • The Kafka Connector streams data between Neo4j and Apache Kafka topics in both directions (source and sink), for event-driven pipelines that keep the graph in sync with the rest of a system — Neo4j Streams / Kafka Connector.

  • The Spark Connector reads and writes Neo4j nodes and relationships as Spark DataFrames, for bulk ETL and analytics jobs run from a Spark cluster — Neo4j Connector for Apache Spark.

  • Getting started with Neo4j — editions, deployment, and the two shells these examples were run from.

  • Advanced Cypher querying — the Cypher patterns (MERGE, subqueries, aggregation) that the loading and refactoring examples above build on.