Why does creating a duplicate constraint error out in 4.x but not in 3.x?

  • Neo4j version: Community 4.0.3
  • Neo4j Mode: Single instance
  • Driver version: Javascript : "4.0.0",
  • Operating system: Mac OS


Neo4j 3.x behavior

Running a Create-constraint query on Neo4j 3.x does not error out even when run multiple times.
The query creates the constraint the first time, but does nothing if run again. (No error though)

Neo4j 4.x behavior

But in Neo4j 4.x, it gives an error if ran more than once:

This broke our design in which we used to create constraints using code.

Do we know why this happened?

Welcome to the community! I might need a bit more because the 4.x behavior is "correct". One could argue the constraint strategy is up there with the data model in terms of when you put them in. Meaning, you decide up front, at that architectural level, what constraints you'd want. So, you'd never re-create them anymore than you decide to change your overall architecture. This is different from indexing for performance BTW. So, best practice would benefit from the restrictions that enforce NOT being able to create constraints if they're there.

So (1), I'd look at what's "broke" to see if that's actually a blessing :slight_smile: and (2) need more to see how you got away with it LOL, in 3.x.


Thank you for the welcome :slightly_smiling_face:

I totally agree with you that the behavior in neo4j 4.x is the correct behavior. But the thing is, because of the way it was designed in 3.x, it let us do something like this:

We have a file which contains all the constraints that we want to exist within the system, say constraints.js. it looks something like this:

const constraints = [
  ['User', 'username'],
  ['UserRole', 'id'],

The idea is that this file runs every time our system restarts, and it runs all the Create constraint statements for each constraint that exists in that array. Now I know that might not be a good strategy to have, but the biggest advantage of that approach was that since creating constraints was idempotent in 3.x, whenever we needed to add a new constraint to our database, we would have to just update that file by adding a new constraint, and the new constraint would be added onto the system automatically after we pushed the changes. We did not have to add the constraint manually to the db. All the older constraints would also run but would have no effect and no error.

Now in 4.x, that design breaks, since running constraints that already exist in the system errors out. Now we have to think of a way to query the system before we run any constraints to check if that constraint exists or not, and to run the constraint only if it does not exist.

Again, I believe 4.x is the correct behavior, but it does make it inconvenient.

Your thoughts?

I agree. I will try and duplicate this because based on what I've done and read, shouldn't happen - even in 3.x. But I've certainly seen that Neo is still a young product in a nascent technology and can have anomalies that are really about something else. Which is why you and I could get distinct results - when it's really not :slight_smile:

But I do like knowing what's up and if I can repro, I'll dig in and see if I can come up with some better answers.