Skip to content

FalkorDB

FalkorDB is an in-memory graph database built on Redis. It offers extremely fast query execution but does not support multi-statement transactions.

database:
datasources:
graph:
type: FALKORDB
host: localhost
port: 6379
database-name: mygraph

Transactions: FalkorDB does not support multi-statement transactions. @Transactional methods work but each query executes and commits independently. An object-manager save is one statement and so still atomic, and so is a saveAll of fragments alone that fits in one; an update is two and a saveAll that holds a view several, and what ran before a failure or a refused save stays applied. By default, startTransaction() logs a debug message, rollbackTransaction() logs a warning, and the first batch of more than one statement logs a warning that it is not applied whole. To enforce strict no-transaction usage (throw on @Transactional, and refuse a batch of more than one statement with NonAtomicBatchException before any of it runs), set:

falkor-db-transaction-mode: STRICT # default: WARN

Jedis: the FalkorDB client needs Jedis 8. Spring Boot’s dependency management sets an older one (6.0.0 on Boot 3.5, 7.4.1 on Boot 4.1), and a managed version in your build wins over the one Drivine declares, so a FalkorDB datasource fails at start-up with NoSuchMethodError on DefaultJedisClientConfig.Builder.autoNegotiateProtocol. Set it yourself:

<!-- Maven, with the Spring Boot parent -->
<properties>
<jedis.version>8.0.1</jedis.version>
</properties>
<!-- Maven, importing a BOM: declare it BEFORE the import -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>8.0.1</version>
</dependency>
</dependencies>
</dependencyManagement>
// Gradle, with the Spring Boot plugin
ext['jedis.version'] = '8.0.1'

Known limitations:

  • Nested pattern comprehensions return NULL (FalkorDB#1888) — Drivine works around this with CALL subquery prologs
  • collect() on null includes null maps (FalkorDB#1889) — Drivine filters with CASE WHEN IS NOT NULL
  • FalkorDB 6 plans an OPTIONAL MATCH of several hops from the labelled node it ends at, and reads every relationship into that label (FalkorDB#3332) — a @GraphPath field leaves the label out of its pattern there and tests it on the node reached
  • FalkorDB 6 scans a label for a WHERE in parentheses, where it would have used an index (FalkorDB#3331) — a load writes none around its conditions or around a keyset cursor (seek), and a load or a count of a fragment writes none around an anyOf that is its whole filter. An anyOf keeps its parentheses everywhere else, and FalkorDB 6 scans for it where nothing else in the filter has an index: beside another condition, nested in another anyOf, in a view, and in a deleteAll

CASCADE DELETE_ORPHAN is supported on current FalkorDB (FalkorDB#1890 is fixed in the graph module Drivine tracks); older builds lacking that fix are not supported for orphan delete.