Mahdi.Kh
August 18, 2026
In this section, we will introduce the service container and service provider concepts for dependency management and service lifecycle management.
One of the important aspects of designing large software applications is managing dependencies (Dependency Management) and service lifecycles (Service Lifecycle Management). In the Danceable ecosystem, these responsibilities are handled by the container and provider packages, which work together to provide a simple, flexible, and extensible structure for managing application services.
A Service Container is a design pattern responsible for managing an application's Dependencies. In simple terms, instead of each part of the application creating the objects it needs, it requests them from the container.
For example, suppose a UserService needs a UserRepository, and the UserRepository itself depends on a Database. Without using a Service Container, you might have code similar to the following:
In small projects, this approach does not usually cause any problems. However, as the number of objects grows, managing and creating dependencies becomes increasingly complex.
With a Service Container, we only need to register how each component should be created once:
Then whenever we need UserService, we simply get it from the container:
The container itself handles these steps:
UserService has already been built.UserRepository.UserRepository, it creates Database if needed.UserService and returns it.So we only place each part into the container, and the container works out for itself how to supply the dependencies.
These two concepts are often confused.
The danceable/container package plays exactly this role: a central place to register, build, and manage all of an application's dependencies.
A Service Provider is a concept used to organize an application's Bootstrap and Shutdown processes.
If we think of the Service Container as a warehouse that stores an application's services, the Service Provider is responsible for filling that warehouse and managing the lifecycle of those services.
In simple terms:
Suppose your application uses these services:
With no service provider, all the code for registering and starting these services ends up in main.go:
As the project grows, main.go turns into the home of every startup operation and becomes hard to maintain. A service provider takes that responsibility out of main.go.
A Service Provider typically has three main responsibilities:
Register: Register dependencies in the Container.
Boot: The boot phase, which includes validating configuration and initializing parts of the application, such as Queues, Workers, or running database Migrations.
Shutdown: The shutdown phase, which takes place just before the application terminates. During this phase, resources are typically released and cleaned up.
Every service provider goes through three main stages over the life of the program:
The first stage is Register. During this stage, the Provider registers its services in the Container. Typically, no external resources, such as database or Redis connections, are created at this point. Instead, only the instructions for creating the services (Factories) are stored in the Container. After the Register stage is complete, the Container knows how to create each service when it is needed.
Once all Providers have completed the Register stage, the Boot stage begins. During this stage, all Providers are booted. The Boot stage typically involves validating configuration and initializing parts of the services.
At the end of the application's execution, the Shutdown stage begins. During this stage, the Provider is responsible for releasing all resources that were used throughout the application's lifetime.
Suppose your project consists of several independent parts:
Each provider is responsible only for its own part. For example:
DatabaseProvider manages only the database.RedisProvider manages only Redis.LoggerProvider manages only the logger.As a result, responsibilities are separated, and adding or removing a service has minimal impact on other parts of the application.
The danceable/provider package serves as the Service Provider. It is responsible for managing the lifecycle of application services and determines which services should be registered in the Container when the application starts, what operations should be performed to prepare and initialize those services, and how the resources they use should be released and cleaned up when the application terminates.