
Top 20 Drupal Interview Questions for Experienced Developers (with Answers and Examples)
This guide provides the most important and frequently asked Drupal interview questions for experienced developers. Whether you’re preparing for a senior developer role or a technical architect position, mastering these Drupal 10-specific questions will help you demonstrate expertise, confidence, and deep technical understanding.
Drupal is a powerful and flexible CMS used by enterprises, governments, and large-scale platforms. Experienced Drupal developers are expected to have hands-on experience with custom module development, performance optimization, complex architectural decisions, and secure code practices.
Table of Contents
1. How does Drupal 10 configuration management work, and how would you manage configurations across environments?
Answer:
Drupal 10 uses the Configuration Management Initiative (CMI) to manage site configuration in YAML files. These files live in the config/sync
directory and include settings, view definitions, field configs, etc. Configurations are exported and imported using Drush or the UI.
Commands:
drush config:export --destination=../config/sync
drush config:import --source=../config/sync
Best Practices:
- Use
config_split
for environment-specific settings - Store configuration in Git for traceability
- Ignore sensitive items using
config_ignore
Example: Manage Google Analytics only in production by using a config split.
2. What’s the difference between a service and a plugin in Drupal?
Answer:
- Service: A PHP object managed by the service container and injected where needed.
- Plugin: A reusable, swappable component discovered via annotations. Plugins are ideal for dynamic and extensible functionality.
Service Example:
# my_module.services.yml
services:
my_module.logger:
class: Drupal\my_module\Logger\MyLogger
Plugin Example:
/**
* @Block(
* id = "custom_block",
* admin_label = @Translation("Custom Block")
* )
*/
class CustomBlock extends BlockBase {
public function build() {
return ['#markup' => $this->t('Hello, Drupal!')];
}
}
3. How do you optimize performance in a large-scale Drupal site with high traffic?
Answer:
- Use Dynamic Page Cache, Render Cache, and BigPipe
- Integrate Redis or Memcached
- Implement Varnish and use CDNs like Cloudflare
- Use Lazy Builders for blocks
- Audit slow queries using
devel
andviews_data_export
Code Tip:
return [
'#markup' => 'Fast content',
'#cache' => [
'contexts' => ['user.roles'],
'tags' => ['node:1'],
'max-age' => 3600,
],
];
4. Explain cache tags, contexts, and max-age with an example.
Answer:
'#cache' => [
'tags' => ['node:45'],
'contexts' => ['user.roles'],
'max-age' => Cache::PERMANENT,
]
- Cache Tags: Automatically invalidates content when specific entities are updated.
- Cache Contexts: Creates different cache entries depending on user role or language.
- Max-age: Time-based expiration. Use
Cache::PERMANENT
for indefinite cache until invalidated.
5. How do you create and structure a custom module in Drupal 10?
Answer:
- Create folder:
modules/custom/my_module
- Create
my_module.info.yml
- Define routes, controllers, services
Sample:
# my_module.info.yml
name: My Module
type: module
core_version_requirement: ^10
// Controller
class MyController extends ControllerBase {
public function content() {
return ['#markup' => $this->t('Custom Page')];
}
}
6. Describe how you use dependency injection in services and controllers.
Answer:
Injecting dependencies makes your code modular and testable.
Service Class:
class CustomService {
protected $logger;
public function __construct(LoggerInterface $logger) {
$this->logger = $logger;
}
}
Controller using ContainerInjectionInterface:
public static function create(ContainerInterface $container) {
return new static(
$container->get('custom.service')
);
}
7. What are best practices for securing a Drupal site?
Answer:
- Escape output:
Html::escape()
,Xss::filter()
- Use permissions system
- Limit user roles and access
- Use HTTPS with secure cookies
- Keep up-to-date using
drush pm-updatecode
Example:
$output = Html::escape($input);
$this->messenger()->addMessage($this->t('Safe content: @content', ['@content' => $output]));
8. How would you debug a production issue with slow page load and high CPU usage?
Answer:
- Use Blackfire or New Relic to profile slow calls
- Check logs via
drush ws
or watchdog - Disable modules to isolate the issue
- Identify N+1 queries or over-rendered blocks
9. How do you create a complex form with conditional logic and multi-step handling?
Answer:
Use Form API with FormStateInterface
. Store interim data in $form_state->set()
and use #states
for dynamic UI.
Snippet:
$form['options'] = [
'#type' => 'radios',
'#options' => ['yes' => 'Yes', 'no' => 'No'],
];
$form['details'] = [
'#type' => 'textfield',
'#states' => [
'visible' => [
':input[name="options"]' => ['value' => 'yes'],
],
],
];
10. How do you use hook_theme and preprocess functions effectively?
Answer:
- Use
hook_theme()
to register templates - Use
template_preprocess_HOOK()
to prepare variables
Example:
function my_module_theme() {
return [
'my_template' => [
'template' => 'my-template',
'variables' => ['items' => NULL],
],
];
}
function template_preprocess_my_template(&$variables) {
$variables['items'] = array_map('ucfirst', $variables['items']);
}
11. Describe how Field API and Entity API work together.
Answer:
Field API allows attaching fields to entities (e.g., nodes, users). Entity API manages entity types, bundles, storage, and behavior. Together, they allow flexible content modeling.
Example:
use Drupal\field\Entity\FieldStorageConfig;
use Drupal\field\Entity\FieldConfig;
$field_storage = FieldStorageConfig::create([
'field_name' => 'field_department',
'entity_type' => 'node',
'type' => 'string',
]);
$field_storage->save();
$field = FieldConfig::create([
'field_name' => 'field_department',
'entity_type' => 'node',
'bundle' => 'article',
'label' => 'Department',
]);
$field->save();
12. What are some advanced use cases for custom entities?
Answer:
Use custom entities when you need lightweight storage or custom workflows outside the node system—such as audit logs, external sync, or custom dashboards.
Example: Custom Entity Annotation:
/**
* @ContentEntityType(
* id = "audit_log",
* label = @Translation("Audit Log"),
* base_table = "audit_log",
* entity_keys = {
* "id" = "id",
* "label" = "title",
* },
* )
*/
class AuditLog extends ContentEntityBase {}
13. How does routing and access control work together?
Answer:
Routing defines paths; access control ensures only authorized users access them.
Example .routing.yml
:
my_module.admin:
path: '/admin/my-custom-page'
defaults:
_controller: 'Drupal\\my_module\\Controller\\CustomController::view'
_title: 'My Page'
requirements:
_permission: 'administer site configuration'
Custom Access Callback:
requirements:
_custom_access: '\Drupal\my_module\Access\CustomAccess::access'
14. What’s new in Drupal 10 that experienced developers should leverage?
Answer:
- Symfony 6 support
- CKEditor 5 integration
- Starterkit theme generator
- Deprecated APIs removed
Example: Generate a theme using Starterkit:
php core/scripts/drupal generate-theme my_theme
Using ES Modules:
import { createApp } from 'vue';
15. How do you implement role-based access in custom logic?
Answer:
Check permissions using hasPermission()
or roles using getRoles()
.
Example:
if ($account->hasPermission('edit any article content')) {
// Allow edit
}
if (in_array('editor', $account->getRoles())) {
// Role-based access
}
16. Scenario: Your site must support 5M+ nodes with full search capabilities. What would you propose?
Answer:
- Use Search API with Solr backend
- Optimize fields and indexing schedule
- Use batch processing for initial indexing
Example: Search API config snippet:
search_api.server.solr_server:
backend: search_api_solr
options:
host: 'solr-host'
port: 8983
17. How would you approach building a multilingual, multi-domain Drupal site?
Answer:
- Use Domain module or multisite
- Enable
language
,content_translation
,interface_translation
Example:
$language_manager = \Drupal::languageManager();
$language = $language_manager->getCurrentLanguage();
$site_language = $language->getId();
Multilingual Block Example:
$build['#title'] = $this->t('Welcome');
18. Describe a situation where you implemented a custom queue worker.
Answer:
Used for background tasks like syncing products from an API.
Queue Item:
$queue = \Drupal::queue('product_sync');
$queue->createItem(['sku' => 'XYZ123']);
Queue Worker:
/**
* @QueueWorker(
* id = "product_sync",
* title = @Translation("Product Sync Worker"),
* cron = {"time" = 60}
* )
*/
class ProductSyncWorker extends QueueWorkerBase {
public function processItem($data) {
// Process API sync logic
}
}
19. How do you build a decoupled front-end architecture with Drupal?
Answer:
- Use JSON:API or GraphQL
- Authenticate using OAuth/JWT
- Use
cache tags
for invalidation
Example: REST endpoint:
GET /jsonapi/node/article
Enable JSON:API module:
drush en jsonapi
20. Scenario: Your deployment must update config without affecting live content edits. What’s your plan?
Answer:
- Use
config_split
for separating dev/staging/prod - Use
config_ignore
for runtime overrides
Post-deploy script:
if (\Drupal::config('system.site')->get('name') !== 'Live Site') {
\Drupal::configFactory()->getEditable('system.site')->set('name', 'Live Site')->save();
}
Conclusion
These 20 Drupal interview questions cover advanced concepts, real-world coding practices, and architectural decision-making. Mastering these topics will help you stand out in senior-level technical interviews.