diff --git a/packages/mikro/src/lib/serialize-entity.ts b/packages/mikro/src/lib/serialize-entity.ts
index c76e576b5..ed7f78bcc 100644
--- a/packages/mikro/src/lib/serialize-entity.ts
+++ b/packages/mikro/src/lib/serialize-entity.ts
@@ -1,6 +1,7 @@
 import { isEmpty } from '@automapper/core';
 import type { AnyEntity } from '@mikro-orm/core';
 import { Reference, Utils, wrap } from '@mikro-orm/core';
+import type { IWrappedEntityInternal } from '@mikro-orm/core/typings';
 
 const excluded = [
     '__gettersDefined',
@@ -14,13 +15,16 @@ const excluded = [
 export function serializeEntity(
     item: AnyEntity,
     itemMetadata: Record<string, unknown> | undefined,
-    toPojo = false
+    toPojo = false,
+    memorized = new Map<AnyEntity, Record<string, unknown>>,
+    skipCheckExisting = false
 ) {
     if (!Utils.isEntity(item)) return item;
     if (toPojo) return wrap(item).toPOJO();
 
     const result = {} as Record<string | symbol, unknown>;
-    for (const key of Reflect.ownKeys(item)) {
+    const keys = Object.keys((wrap(item) as IWrappedEntityInternal<AnyEntity>).__meta.properties);
+    for (const key of keys) {
         if (typeof key === 'symbol' || excluded.includes(key)) {
             continue;
         }
@@ -33,6 +37,8 @@ export function serializeEntity(
                 return serializeEntity(
                     snapshot as AnyEntity,
                     keyMetadata,
+                    true,
+                    memorized,
                     true
                 );
             });
@@ -40,23 +46,37 @@ export function serializeEntity(
         }
 
         if (Reference.isReference(value)) {
+            const isExisting = memorized.has(value);
+
+            if (!skipCheckExisting && isExisting) {
+                result[key] = memorized.get(value);
+                continue;
+            }
+
             if (!value.isInitialized()) {
+                memorized.set(value, wrap(value).toPOJO());
                 result[key] = serializeEntity(
                     wrap(value).toPOJO(),
-                    keyMetadata
+                    keyMetadata,
+                    false,
+                    memorized,
+                    !isExisting
                 );
                 continue;
             }
 
+            memorized.set(value, value.getEntity() as Record<string, unknown>);
             result[key] = serializeEntity(
                 value.getEntity(),
                 keyMetadata,
-                typeof keyMetadata === 'object' && isEmpty(keyMetadata)
+                typeof keyMetadata === 'object' && isEmpty(keyMetadata),
+                memorized,
+                !isExisting
             );
             continue;
         }
 
-        result[key] = serializeEntity(value, keyMetadata);
+        result[key] = serializeEntity(value, keyMetadata, false, memorized, false);
     }
 
     if (result['id'] == null && item['id'] != null) {