Entity Identity vs Database Primary Key

Today, we’ll discuss the difference between identity in the DDD sense and database primary keys. We often mix the two together but are they really the same thing?

Entity Identity

In the context of DDD, identity is something inherent to an entity. Only entities have it; it’s something that uniquely identifies them among all other entities.

For example, we deem two people as being different regardless of any “attributes” they possess. It could be, by sheer coincidence, that they have the same name, age, address, etc. We still wouldn’t treat them as the same person because of that. Each human has an inherent identity that differentiates them from other people.

But what is this identity, exactly?

The thing is, you can’t pinpoint it. You cannot tell what comprises someone’s identity. And that’s by design. The reason why stems from the characteristics of the concept of identity: each identity must be immutable and globally unique.

That’s how we, humans, operate with objects we need to keep track of. We assign an intangible, unique label to each of them and then use that label to identify that object among all others.

That’s how you keep track of people too. A person could undertake a huge transformation (for example, grow up from a kid into a fully developed adult) and you still know that it’s the same individual. That’s because when you first meet that person, you assign to them a unique identity which doesn’t change even after the person himself transforms drastically.

Because of these two characteristics – immutability and uniqueness – you can’t really use any of the entity’s natural attributes as its identity. Those attributes tend to change over time. And they tend not to be unique either.

Want to use the person’s full name as their identity? Nope, names are not unique. Social security number (SSN)? Nope, those can change.

Of course, when it comes to domain modeling, you need to remember that any model is just that – a model. A simplified representation of the real world, sophisticated just enough to be useful. You don’t need to reflect the full complexity of the problem domain in your model.

And so, it could be that within some particular domain model, it’s just fine to use a person’s SSN (or email) as their identity. But those tend to be quite simple models. If you work on anything more or less complex, you would inevitably run into issues trying to reconcile a change in the supposedly immutable identity. And all complex systems experience such changes. Just consider a use case of incorrectly entered email. Modifying it should not alter who the person is.

So, in general, the use of natural attributes (attributes that come from the real world) is not a good way to represent an entity’s identity. It must be something intangible; something that you artificially create and assign to the entity and thus can ensure that it is both unique and immutable.

Database Primary Key

What about the database primary key? How is it related to the concept of identity?

Nohow. It is a completely separate concept, not related to DDD or domain modeling.

But here’s the thing. You need to persist your entities somehow. And not only persist but also restore them later and be able to keep track of their identity. Which means that the identity must not change during this persist-restore cycle.

And what database feature allows you to do that best? That’s right, primary keys.

It turns out that the database primary key is a good approximation for the concept of identity from Domain-Driven Design. Databases provide durability which allows you to ensure the identity doesn’t change after you persist it. And primary keys in particular help achieve uniqueness across all identities in your system. The row’s table name plus its primary key make for a great implementation of the concept of identity.

You might have heard about the guideline of never using a natural primary key when designing the database. Martin Fowler wrote about it in his Patterns of Enterprise Application Architecture. Now you know where this guideline comes from.

Natural primary keys are not a good fit for representing an identity precisely because they tend to change over time (if only by mistake) and might not be that unique after all. Surrogate primary keys deal with these issues much better. You can assign them once when creating a record and then keep immutable even after modifying such foundational properties as email or SSN. It’s also very easy to ensure their uniqueness as there are no external constraints on what those keys should look like.

Value Objects and Identity

Let’s also mention value objects here. Now, I hear you saying: don’t value object have no identity? That’s true but there’s another way to view this: the identity of a value object spans across all its attributes.

But isn’t there a contradiction? Didn’t I just tell you that natural properties don’t make for a good identity?

There’s no contradiction here because we don’t need to keep track of value objects. They are immutable. As soon as you need to introduce a change in a value object, you create a new one and replace the old one with it.

Because value objects are immutable, we automatically fulfill the first requirement of Identity: immutability.

What about uniqueness? How do we achieve it?

Well, remember that value objects are interchangeable. We can freely replace one with another as long as their attributes match. And there’s also another way to view this: if two value objects are interchangeable, it means they are the same. They have the same identity. Otherwise, you wouldn’t be able to use one in place of the other (just as you can’t use one John in place of another John unless they are the same person).

So, each value object is unique by definition. Which gives us the other component of Identity.

Therefore: Value Object == Its Properties == Identity

Entity Identity vs Database Primary Key: Summary

  • An entity’s Identity is intangible
  • Identity is immutable and globally unique
  • Don’t use natural attributes as the entity’s Identity. They change over time and they might not be unique
  • Database primary keys are a good approximation for the concept of Identity
  • Don’t use natural primary keys. Surrogate primary keys are the best fit for entities’ identities
  • The attributes of a Value Object are its own identity


Entity vs Value Object: the ultimate list of differences


  • Michael Hodgson

    What are your thoughts on using database generated id’s as domain identities (auto-increment), vs identities generated as part of the application (e.g. GUIDs or systems like twitter’s snowflake)?

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      I personally prefer HiLo (built-in into NHibernate, EF Core devs said EF should have it too by now). It’s cleaner as it doesn’t require a db roundtrip to get a new Id for an entity (well, it does, but only once every 10 or whatever number you configure it for, and the call is done independently from saving the object itself which is a good thing too). For simple scenarios, auto-increment is good too.

      I don’t quite like GUIDs. They are too clunky to work with (just in terms of manual manipulation) but might be necessary if you need to exclude the possibility of enumeration attacks. Raw GUIDs are also slower in high load scenarios as they require page splits and primary key rebalancing (need to use Sequential (comb) Guids to avoid that).

  • serge bouschet

    Thanks for sharing this very good intro to Entity and Identity. I have to say you lost me on database keys though. There is a fundamental difference between surrogate primary keys in databases, often used for technical reasons (referential integrity – as best practices, these shouldn’t be exposed to end users) and true Business Keys (e.g. Customer No) which are used throughout the enterprise to Identify records (entities) and fulfil the unique and immutable properties you describe.
    Data exists in the context of business processes and such we must always look for a tangible connection.

    • Jordan Silva

      I completely agree. Also, using database ids to identify an entity causes serious problem when that entity has to be inserted into a HashMap or even a Set (which is a HashMap). It also means that every single object that has not yet been persisted are equals!

      • http://enterprisecraftsmanship.com/ Vladimir Khorikov

        Using natural keys as entity Ids is a bad idea and isn’t at all how the real world entities work if you think about it. I recommend that you decouple entity ids from natural keys (SSN, email, etc). And you don’t have to rely on the database to generate them, there are way to create ids together with the creation of a new entity (HiLo for example).

        • Jordan Silva

          What about equals? How to compare two entities based on the db ids? Then how to guarantee equals and hash code contract? How do I know I have no duplication on my database? You have no choice but look at entity’s natural key.

          • http://enterprisecraftsmanship.com/ Vladimir Khorikov

            What about equals? How to compare two entities based on the db ids?

            The entity’s id is the same as in the database, so you compare the entities by their in-memory ids (which are also mapped to the db’s ids).

            Then how to guarantee equals and hash code contract?

            By not changing that id after the user is created.

            How do I know I have no duplication on my database?

            You’ll need to do an additional call to the DB to see if there are any duplication (e.g users with the same email), but there’s no need to check if the surrogate id is unique – you can ensure its uniqueness without calling the db. One popular way is to use GUIDs, another – HiLo ( https://stackoverflow.com/questions/282099/whats-the-hi-lo-algorithm )

          • Jordan Silva

            You’ll need to do an additional call to the DB to see if there are any duplication (e.g users with the same email)

            That’s exactly my point, you have to check the Entity’s natural key!

            My question about the equals and hashCode was much deeply that what you answred. My point is that you cannot say if an entity already exists only looking to the database id!

            Let me put a more practical example.

            A have a list of Users and I want to know if the user A is present in that list.

            Let’s consider I have the following Class following the use of Database Id as the Entity’s key:

            class User {
            long id;
            String email;

            User(long id, String email) {
            this.id = id;
            this.email = mail;

            boolean equals(User another) {
            return this.id == another.id

            int haschCode() {
            return id;

            Now what I have to do is to call the contains method of the list to verify if the User already exists in the list:

            List existingUsers = new ArrayList()
            existingUsers.add(new User(1, "[email protected]"))
            existingUsers.add(new User(2, "[email protected]"))
            existingUsers.add(new User(3, "[email protected]"))

            // The id assigned to that object is unique as it is following HiLo, therefore there is no element in the list with that id.
            User newUser = new User(4, "[email protected]")
            if (existingUsers.contains(newUser) {
            System.out.println("User exists");
            } else {
            System.out.println("User does not exist");

            And you can clearly see, this code will print “User does not exist” even though it is expected to already exist.

            So why would I create an Entity that is not even able to find itself in a list? You may solve few problems using the db id (will you?), but it will make your life worse in many other aspects that I don’t think it is a good idea to do that.

          • http://enterprisecraftsmanship.com/ Vladimir Khorikov

            I understand your point, but the thing is – entities shouldn’t be defined by their properties, it goes against the whole concept of being an entity: https://enterprisecraftsmanship.com/2016/01/11/entity-vs-value-object-the-ultimate-list-of-differences/

            In your example, the search in the collection of users needs to be done explicitly by the email, instead of relying on GetHashCode(). Such a search can usually be encapsulated away. For example, if that list of users belongs to an organization, you can have a method like:


          • Jordan Silva

            Those are your own words from the link you sent above:

            And finally, with structural equality, we consider two objects equal if all of their members match:

            I didn’t add any other field besides email just to be short, but assume there’re other fields in the class. Therefore, it doesn’t apply your attempt to say User is a Value Object.

            In Java we have the equals method so we don’t need to write a separete method for each object in order to compare them. By definition, the equals method should be enough to say if two instances are equal or not. So if I have to write another method that will actually tell me if two instances are equal, it will make my life much harder as lot’s of standard solutions will just not work.

            Finally, I should be able to apply Entity/Value Object concempts in applications that do not use database. I can generalize your idea and say that you tell us to use a created key that does not belong to the instance, but has the only purpose of beeing the entity’s key, and that, in my opinion, goes against the definition of Entity.

            I would buy that idea if it would simplify my life, however, as I have demostrated, such practice will only make my life harder. Thus, it’s better to stick with the definition of Entity and use the natural key that applies to your model.

  • Jonathan Bolduc

    What about letting the user enter a textual id which would be more meaningful to the domain than a guid or some other autogenerated id ?
    For example, I want to create a calendar event, i could enter an id like “20181115A”. The id field could also so be auto-populated, derived from another attribute field like a name for example, in order to reduce the user work charge.

    • http://enterprisecraftsmanship.com/ Vladimir Khorikov

      This would be a natural Id. The general rule here is – don’t use a natural Id because it can change, there’s always a possibility (albeit small) of it. Instead, create a surrogate Id (a guid, etc) and add this field containing “20181115A” separately. You’ll be able to get the best of the two worlds – show the user the more meaningful value but still not rely on it to determine the entity identity.

      • Jonathan Bolduc

        ok thanks for the reply

      • Jonathan Bolduc

        The database already use a surrogate key besides this domain identifier, you suggest to also put this surrogate key in the domain entity definition too ? It does not seem a good idea to me to put a database key in the domain entity… Creating a third id value seems excessive complexity.

        • http://enterprisecraftsmanship.com/ Vladimir Khorikov

          You’ll need to map the entity Id to the database’s Id somehow. Not sure what you mean by third id, but there’s no way around putting the DB’s surrogate id into the entity. You can encapsulate it away from the client code though.

        • Shannon Luna