Needs review
Project:
Paragraphs
Version:
8.x-1.12
Component:
Code
Priority:
Normal
Category:
Bug report
Assigned:
Unassigned
Reporter:
Created:
12 Jan 2022 at 16:16 UTC
Updated:
25 Mar 2026 at 15:25 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #2
coufu commentedI'm experiencing a similar issue with Paragraphs. They seem to not be able to scale. I don't have as many as you (200 is a lot!), but I do have probably about 50. Then the problem is compounded with translations etc. Does anyone have any reading material around how to optimize sites that rely heavily on Paragraphs?
Comment #3
michaellenahan commentedThe drupal sites I am working on have many nested paragraphs. One example with a total of 167 paragraphs is not unusual. When we save the node, entity_reference_revisions `EntityReferenceRevisionsItem::preSave()` sets `$needs_save = TRUE` for all these paragraphs, without any check on whether they have been changed or not.
I have proposed a patch for that in the entity_reference_revisions issue queue:
https://www.drupal.org/project/entity_reference_revisions/issues/3267490...
With that patch in place, two changes are needed in paragraphs module:
Change 1: Conditional `setNeedsSave(TRUE)` in `ParagraphsWidget::massageFormValues()`
Only call `setNeedsSave(TRUE)` for paragraphs in `edit` mode. Paragraphs in `closed` or `preview` mode don't have their form values extracted (no user changes are possible), so they don't need saving.
Change 2: `Paragraph::onChange()` override for programmatic change detection
Adds an `onChange()` method to `Paragraph.php` that auto-sets `needsSave(TRUE)` whenever a field value changes programmatically (via `$paragraph->set()`, `$paragraph->get()->setValue()`, etc.). This ensures programmatic modifications are never silently dropped.
The `onChange()` implementation also:
- Propagates `needsSave(TRUE)` to the untranslated base entity (for translation support)
- Propagates `needsSave(TRUE)` to the immediate parent paragraph (for nested paragraph support)
Comment #4
michaellenahan commentedComment #6
michaellenahan commentedI did some more testing. Patch and update to MR to follow.
Comment #7
michaellenahan commentedComment #8
michaellenahan commentedComment #9
michaellenahan commentedComment #10
michaellenahan commentedThe original patch (comment #3) handled the two main cases: form edits and programmatic changes. But during testing, we found that Drupal's internal machinery triggers onChange() in ways that look like real edits but aren't — particularly revision metadata fields being set during createRevision() in form build, which silently re-flagged every paragraph before the user even submitted the form.
We also found code paths that bypass the field API entirely (behavior settings), a stale form state value that masked a langcode propagation bug, and the drag-and-drop reorder function unconditionally flagging all paragraphs. Each of these was a way that needsSave(TRUE) was being set when it shouldn't be, or not being set when it should be — undermining the optimization or causing silent data loss.
Despite these changes, this current patch 3258261-10.patch (and the associated #3267490 patch), we are able to significantly (90%+) reduce save time.
Example timings for our 167-paragraph node are as follows:
Saving the node with no changes - previously: 968ms / 167 paragraph saves - now: 1 paragraph save
Drag and drop paragraphs - previously: 968ms / 167 saves - now: ~400ms / ~67 saves
The drag-and-drop saves are caused by AJAX form rebuild, we decided not to go down that rabbit-hole for now. Even still, 167 -> 67 saves is a significant improvement.