Flattening Deeply Nested Paragraphs Across 37 Drupal 10 Healthcare Websites
Restructuring a Multisite Content Model as the Only Developer
A first-person case study on restructuring the content model of 37 Drupal 10 healthcare websites: flattening and merging nested Paragraphs into plain fields, one reusable migration structure, and unit, Drupal Test Traits and smoke testing before release.
Executive Summary
This was not a version upgrade. The 37 websites were already on Drupal 10. The problem was the shape of their content.
Over time, the sites had come to store content in Paragraphs nested inside Paragraphs, several levels deep, with fields scattered across those levels. A single piece of content could be a content type holding a paragraph, holding another paragraph, holding the fields that actually mattered.
I was hired to restructure that content model. I designed and ran migrations that flattened the nesting into simpler content types with plain fields, merging structures where several had to become one. The same migration structure worked across all 37 sites.
I delivered it as the only developer, and made sure it was tested, verified and production-ready before it shipped.
The Problem With Deep Nesting
Paragraphs is a powerful Drupal module. It is also easy to overuse. Each level of nesting is reasonable when it is added, and the cost only shows up later:
- Editors have to open several layers of widgets to change one value.
- Developers have to traverse entity references level by level to read or render a field.
- Queries, search indexing and APIs have to join through every level to reach the data.
- Every new site in a multisite network inherits the same complexity.
The target was the opposite: one content type with a small set of plain fields that held what the nested structures had been holding.
Architecture Overview
Engineering Approach Note
AN-001 — Flatten, Then Merge
- Approach
- Read nested Paragraphs, write plain fields on a simpler content type
- Hard case
- Paragraphs inside paragraphs inside paragraphs, with fields at several levels
Context
Some structures mapped one-to-one onto a field. Others were several nested structures that only made sense together and had to become a single field or a single content type.
The Approach
Treat it as a migration within the same site rather than a manual edit: walk each nested structure down to the fields that carry content, then write them as plain fields on the target content type, merging structures where the target model needed one value instead of several.
Tradeoffs
A migration takes longer to write than a script that moves a few fields. It is also repeatable, reviewable and testable, which matters when the same change has to land on 37 sites.
Engineering Approach Note
AN-002 — One Migration Structure for 37 Sites
- Approach
- Design the migration once, run it on every site in the network
- Result
- The same structure worked across all 37 websites
Context
Writing 37 slightly different migrations would have multiplied the work and the bugs by 37.
The Approach
Build the structure around what the sites shared, so that each site ran the same migration rather than its own variant.
Tradeoffs
A shared structure has to tolerate the variations between sites. Getting that right up front is what made it possible for one developer to deliver the whole network.
Engineering Approach Note
AN-003 — Production-Ready, Not Just Migrated
- Testing
- Unit tests, Drupal Test Traits (DTT) tests, smoke tests
- Operations
- Timeout issues found and resolved before release
Context
A content migration can finish without errors and still leave content wrong. On healthcare websites, wrong content is not a cosmetic problem.
The Approach
I added unit tests and Drupal Test Traits tests, ran smoke tests on the result, resolved the timeout issues that appeared while migrating, and verified and validated the migrated content before shipping it.
Tradeoffs
Testing a migration takes real time on a tight timeline. It is also what let a single developer ship a change across 37 production sites with confidence.
Delivering Alone
A second developer was brought in to help with the project. It did not work out, and I carried the work through to the end on my own. One developer delivered what had been planned for two.
Lessons Learned
Content models need refactoring too. Nesting that made sense one level at a time can become the main cost of a platform.
Multisite work rewards a single structure. The cheapest migration to maintain is the one you only write once.
“Migrated” is not “done”. Tests, smoke checks and validation are what turn a migration into a release.
Approach Notes Summary
| Note | Topic | Nature |
|---|---|---|
| AN-001 | Flatten, then merge | Implemented |
| AN-002 | One migration structure for 37 sites | Implemented |
| AN-003 | Production-ready, not just migrated | Implemented |
Final Thoughts
The same agency later brought me onto a much larger engagement, a federated search architecture for a global healthcare company, which I describe in ECS-001: Designing a Federated Enterprise Search Platform for 150+ Websites.
Explore all Engineering Case Studies.