
If you have ever encountered a vague but catastrophic error like this:
1 | Fatal error: Allowed memory size of 134217728 bytes exhausted (tried to allocate 4096 bytes) |
… while working in a Symfony project using Doctrine and the Symfony serializer, you are not alone 🙂
This post walks you through a real-world debugging journey that ended up pinpointing a subtle but devastating issue: Symfony’s default serializer uses Doctrine metadata – and when used carelessly, it can eat up all your memory.
The Setup
I was working on a Symfony-based backend with the following stack:
- Symfony Messenger
- Doctrine ORM
- Symfony Serializer
- API Platform (used, but not involved in this case)
- Docker + DDEV environment
I had a class, let’s name it RequestLog used to store large request/response payloads (e.g., for debugging or backup purposes). It looked like this:
1 2 3 4 5 6 7 8 9 10 | class BookingDbBackup { #[ORM\Column(type: Types::TEXT)] private ?string $request = null; #[ORM\Column(type: Types::TEXT)] private ?string $response = null; // ... } |
The problem showed up when serializing large data into this entity and then trying to serialize the whole entity again.
The Symptom
During a background task, the memory consumption suddenly spiked and caused this error:
1 | Fatal error: Allowed memory size of ... exhausted |
With the stack trace pointing deep into:
1 | Symfony\Component\Serializer\NameConverter\MetadataAwareNameConverter.php |
The Root Cause
After some head scratching, test scripts, and dead ends, it became clear:
Symfony’s default
ObjectNormalizeruses Doctrine’s metadata extractor if present.
That means every entity being serialized pulls in its entire Doctrine metadata, including relationships, even if you don’t want or need them.
In our case, RequestLog had huge JSON fields that didn’t need metadata or special treatment.
The default serializer was overkill.
The Solution: A Lightweight Serializer Adapter
We created a dedicated, minimal serializer that avoids Doctrine metadata completely:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | class LightSerializerAdapter implements SerializerAdapterInterface { private SerializerInterface $serializer; public function __construct() { $this->serializer = new Serializer( [new ObjectNormalizer(null, null, null, null)], [new JsonEncoder()] ); } public function serialize(mixed $data, string $format, array $context): string { return $this->serializer->serialize($data, $format, $context); } // ... } |
Then we injected this into our SerializerService and called it explicitly:
1 | $this->serializerService->serialize($task->getRequest(), adapter: 'light'); |
Takeaways
- Symfony’s Serializer is powerful — but dangerous with Doctrine entities and large payloads.
- Avoid using the default
ObjectNormalizerwhen serializing internal debug or backup data. - Use lightweight, no-metadata serializers where appropriate.
- Don’t rely solely on API Platform annotations to control exposure – the serializer is used everywhere.
Final Words
This issue is sneaky. It won’t crash in dev, and it might only surface under production-level loads. If you’re dealing with serialization of entities, especially those with large or nested data, consider this a warning.
Build your own serializer or explicitly strip metadata – and stay in control of memory usage.