Performance Optimization
When to Use
Apply these patterns when AJAX requests are slow, causing excessive database queries, large DOM updates, or timeouts on large operations.
Decision
| If you need... | Use... | Why |
|---|---|---|
| Reduce DOM updates | Return smallest possible element | Replace only changed elements, not entire containers |
| Large operations | Batch API | Prevents timeout for >100 items or >30s operations |
| Fast repeated requests | CacheableAjaxResponse | Avoids redundant server processing |
| Efficient queries | Entity query with range() | Reduces database load and memory use |
Pattern
// Return smallest possible element (not entire form)
public function ajaxCallback(array &$form, FormStateInterface $form_state) {
return $form['subcategory']; // NOT $form
}
// Limit database results
private function loadItems($category_id) {
$nids = $this->entityTypeManager->getStorage('node')->getQuery()
->condition('type', 'item')
->condition('field_category', $category_id)
->range(0, 50) // Always limit results
->sort('title')
->accessCheck(TRUE)
->execute();
return $this->entityTypeManager->getStorage('node')->loadMultiple($nids);
}
// Cacheable response for shared content
use Drupal\Core\Cache\CacheableAjaxResponse;
public function ajaxCallback(array &$form, FormStateInterface $form_state) {
$response = new CacheableAjaxResponse();
$response->addCommand(new ReplaceCommand('#target', $content));
$response->getCacheableMetadata()
->setCacheMaxAge(300)
->setCacheContexts(['user.permissions']);
return $response;
}
Performance thresholds:
| Operation Type | Target Time | Action if Exceeded |
|---|---|---|
| Simple field update | <200ms | Optimize query, reduce DOM update size |
| Autocomplete query | <500ms | Add result limit, index search fields |
| File upload (2MB) | <5s | Use progress bar, increase PHP limits |
| Batch operation | <30s total | Use Batch API with progress tracking |
Reference: core/lib/Drupal/Core/Cache/CacheableAjaxResponse.php
Common Mistakes
- Wrong: Returning entire form when only one element changed → Right: Return only the specific element that changed
- Wrong: No result limits on database queries → Right: Memory exhaustion; always use
range(0, N) - Wrong: Not using Batch API for large operations → Right: Timeouts; use batch for >100 items
- Wrong: Caching user-specific content without context → Right: Data leaks; verify cache contexts match data sensitivity
- Wrong: No progress indicators for long operations → Right: Add progress for operations taking >2 seconds
See Also
- Response Caching
- CSRF Protection
- Reference:
core/lib/Drupal/Core/Entity/Query/QueryInterface.php