Install
$ agentstack add skill-trebormc-drupal-ai-agents-performance-audit ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Performance Audit
Diagnostic Commands
# Enabled modules count — over ~100 on a simple site suggests module bloat
ssh web drush pm:list --status=enabled --format=list | wc -l
# Recent PHP errors — repeated warnings/notices on every request cost performance
ssh web drush watchdog:show --type=php --count=20
# Slow queries counter — a value > 0 that grows on reload means slow SQL to investigate
ssh web drush sqlq "SHOW STATUS LIKE 'Slow_queries'"
For function-level profiling, use the xdebug-profiling skill.
Baseline Measurement (do this BEFORE and AFTER any change)
# Page timing from inside the web container (timing measurement only — this is
# NOT functional testing; functional testing still uses Playwright, never curl):
ssh web curl -s -o /dev/null -w "first: %{time_total}s\n" http://localhost/PATH
ssh web curl -s -o /dev/null -w "second (warm cache): %{time_total}s\n" http://localhost/PATH
Record both numbers. After your fix, re-run and compare — if there is no measurable improvement, the bottleneck is elsewhere.
How to Detect N+1 Queries
- Profile the slow page with the xdebug-profiling skill (profile mode).
- In the analyzer output, look for entity load / query functions with a very high call COUNT (e.g.
Drupal\Core\Entity\...::loadcalled 200 times). - Find the loop in the code calling
load()per item and replace withloadMultiple(). - Alternative: if the devel/webprofiler module is installed, enable its DB query log and look for many near-identical queries.
Caching Strategy
Cache Tags (What to invalidate)
$build['#cache']['tags'] = ['node:123', 'node_list'];
// Custom tags
$build['#cache']['tags'] = Cache::mergeTags(
$entity->getCacheTags(),
['mymodule:custom_list']
);
Cache Contexts (When to vary)
$build['#cache']['contexts'] = [
'user.permissions',
'user.roles:authenticated',
'url.query_args',
'languages:language_content',
];
Cache Max-Age
$build['#cache']['max-age'] = 3600; // 1 hour
$build['#cache']['max-age'] = 0; // Never cache (use sparingly!)
$build['#cache']['max-age'] = Cache::PERMANENT; // Until invalidated
Lazy Builder for Dynamic Content
$build['dynamic_part'] = [
'#lazy_builder' => [
'mymodule.lazy_builder:build',
[$entity_id],
],
'#create_placeholder' => TRUE,
];
Database Optimization
Avoid N+1 Queries
// BAD - N+1 queries
foreach ($nids as $nid) {
$node = Node::load($nid);
}
// GOOD - Single query
$nodes = Node::loadMultiple($nids);
Efficient Entity Queries
$query = \Drupal::entityQuery('node')
->condition('type', 'article')
->condition('status', 1)
->range(0, 50)
->sort('created', 'DESC')
->accessCheck(TRUE);
$nids = $query->execute();
Performance Audit Checklist
Database
- [ ] No N+1 queries (check: "How to Detect N+1 Queries" above)
- [ ] Proper indexes on custom tables (check:
ssh web drush sqlq "EXPLAIN SELECT ...") - [ ] Entity queries use accessCheck() (check:
grep -rn "entityQuery" $DDEV_DOCROOT/modules/custom/) - [ ] Batch API for bulk operations (>50 items)
Render System
- [ ] Cache tags on all render arrays (check:
grep -rn "'#cache'" $DDEV_DOCROOT/modules/custom/) - [ ] Cache contexts appropriate
- [ ] Lazy builders for expensive/dynamic parts
- [ ] No logic in Twig templates (check with the twig-audit skill)
Views Specific
- [ ] Query caching enabled
- [ ] Rendered output caching enabled
- [ ] Pager configured (no unlimited)
- [ ] Only necessary fields loaded
Optimization Workflow
Step 1: Baseline Measurement
Measure cold cache time, warm cache time, query count, memory usage.
Step 2: Identify Bottlenecks
Priority: Database queries → Uncached render arrays → Heavy computations → External calls
Step 3: Implement Fix
| Problem | Solution | |---------|----------| | N+1 queries | Use loadMultiple() | | Repeated computation | Add caching layer | | Dynamic user content | Use lazy builder | | Heavy view | Add Views caching | | Large entity loads | Load only needed fields |
Step 4: Measure Improvement
Re-run baseline tests. Document before/after metrics.
Step 5: Validate
- Verify cache invalidation works correctly
- Test edge cases (anonymous vs authenticated)
Library Optimization
# Only load JS/CSS when needed
mymodule.specific:
js:
js/specific.js: {}
dependencies:
- core/drupal
Reference Skills
- xdebug-profiling — function-level timing, call trees, cachegrind
- drupal-debugging — cache debugging, slow query diagnosis
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: trebormc
- Source: trebormc/drupal-ai-agents
- License: Apache-2.0
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.