Services API

The Services API is Drupal's dependency injection container, a registry of replaceable objects that classes receive through their constructors.

Learn DrupalDrupal glossary Last updated

In Drupal, a service is an object that the service container creates and manages, such as the objects for database access, sending email or translating text. The Services API is the system around it. A module declares a service in a *.services.yml file, and other code asks the container for it by name. Drupal adopted the design from the Symfony DependencyInjection component.

How services work in Drupal 11

A service has a unique machine name, a class and, when the class needs other services, a list of arguments. Core defines its services in core.services.yml. Core modules and contributed modules define theirs in MODULE_NAME.services.yml. A definition from the core documentation looks like this:

path_alias.manager:
          class: Drupal\path_alias\AliasManager
          arguments: ['@path_alias.repository', '@path_alias.prefix_list', '@language_manager']

An @ before a name injects another service, a name between % signs refers to a parameter, and @? marks an optional dependency. Other keys include factory, parent and tags. The container can also autowire arguments from the constructor's type hints, and core's own service files use autowire: true on some services.

The point of the container is replaceability. Code that asks for a service by name gets whichever class is currently registered, so another module can provide an alternative class for the same service. Drupal compiles all definitions into one container and caches it; a full cache rebuild invalidates and rebuilds that cached container.

Example

Define a service in my_module.services.yml:

services:
          my_module.greeter:
            class: Drupal\my_module\Greeter
            arguments: ['@current_user']
<?php

        namespace Drupal\my_module;

        use Drupal\Core\Session\AccountProxyInterface;

        class Greeter {

          public function __construct(protected AccountProxyInterface $currentUser) {}

          public function greet(): string {
            return 'Hello, ' . $this->currentUser->getDisplayName();
          }

        }

A controller or a plugin that has a create() method receives the container and calls $container->get('my_module.greeter'). Code with no such method can use \Drupal::service('my_module.greeter').

Common mistakes

  • Creating the class with new. Core's topic says to always get a service through the container, so that an overriding class is honored.
  • Reaching for \Drupal::service() inside classes. Service location hides dependencies and makes unit tests harder. Inject the service instead.
  • Skipping the cache rebuild. A new or changed entry in a services file is not used until the cached container is rebuilt. Drush's cache:rebuild command, alias cr, rebuilds all caches.
  • Confusing it with web services. The Services API in core does not expose REST endpoints. Those come from the JSON:API and RESTful Web Services modules.

For marketing and content teams

You never edit services, but they explain why a developer can change how the site behaves in one place. Swapping the class behind a service such as path handling or mail changes every feature that asks for it, without touching those features. If your team needs to feed content to an app or another system, that is a web services question, and the answer is a different module, not this API. For the surrounding extension points, see Plugin API and hooks.

Sources

Questions about Services API

No. The Services API is the container that Drupal core uses for its own objects. The contributed Services module exposes HTTP endpoints to external clients. Its project page lists no supported stable release and recommends the core JSON:API or RESTful Web Services modules for newer Drupal versions.

Core's documentation says to use dependency injection when you can, through constructor arguments or a create() method, because it makes unit tests easier and keeps dependencies visible. Use \Drupal::service() only in code that has no other way to reach the container.

Add a class named after your module with ServiceProvider at the end, for example MyModuleServiceProvider, in the top-level module namespace. It extends ServiceProviderBase and implements alter(), where you call setClass() on the service definition.

Cite this definition

"Services API." DXPR Drupal glossary, https://dxpr.com/hc/documentation/learn-drupal/drupal-glossary/services-api. Last updated October 26, 2026.

Related terms

All Drupal terms from A to Z