diff --git a/bin/cli b/bin/cli
index ea8cb5c3..7f512eb0 100755
--- a/bin/cli
+++ b/bin/cli
@@ -2,7 +2,7 @@
 <?php
 declare(strict_types=1);
 
-use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerInterface;
 use Symfony\Component\Console\Application as CliApp;
 
 /** @var ContainerInterface $container */
diff --git a/composer.json b/composer.json
index 7f2677c2..9c110af8 100644
--- a/composer.json
+++ b/composer.json
@@ -20,6 +20,7 @@
         "cakephp/chronos": "^1.2",
         "cocur/slugify": "^3.0",
         "doctrine/cache": "^1.6",
+        "doctrine/dbal": "^2.9",
         "doctrine/migrations": "^2.0",
         "doctrine/orm": "^2.5",
         "endroid/qr-code": "^1.7",
diff --git a/config/cli-config.php b/config/cli-config.php
index 3c80ee16..524fcf19 100644
--- a/config/cli-config.php
+++ b/config/cli-config.php
@@ -3,7 +3,7 @@ declare(strict_types=1);
 
 use Doctrine\ORM\EntityManager;
 use Doctrine\ORM\Tools\Console\ConsoleRunner;
-use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerInterface;
 use Zend\ServiceManager\ServiceManager;
 
 /** @var ContainerInterface|ServiceManager $container */
diff --git a/module/CLI/src/Factory/ApplicationFactory.php b/module/CLI/src/Factory/ApplicationFactory.php
index e866c190..007e8a28 100644
--- a/module/CLI/src/Factory/ApplicationFactory.php
+++ b/module/CLI/src/Factory/ApplicationFactory.php
@@ -3,7 +3,7 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\CLI\Factory;
 
-use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerInterface;
 use Shlinkio\Shlink\Core\Options\AppOptions;
 use Symfony\Component\Console\Application as CliApp;
 use Symfony\Component\Console\CommandLoader\ContainerCommandLoader;
diff --git a/module/EventDispatcher/src/Async/TaskRunnerDelegator.php b/module/EventDispatcher/src/Async/TaskRunnerDelegator.php
index 8c0be644..7c87826b 100644
--- a/module/EventDispatcher/src/Async/TaskRunnerDelegator.php
+++ b/module/EventDispatcher/src/Async/TaskRunnerDelegator.php
@@ -3,19 +3,15 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\EventDispatcher\Async;
 
-use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerInterface;
 use Psr\Log\LoggerInterface;
 use Swoole\Http\Server as HttpServer;
-use Zend\ServiceManager\Factory\DelegatorFactoryInterface;
 
-class TaskRunnerDelegator implements DelegatorFactoryInterface
+class TaskRunnerDelegator
 {
-    public function __invoke(
-        ContainerInterface $container,
-        $name,
-        callable $callback,
-        ?array $options = null
-    ): HttpServer {
+    public function __invoke(ContainerInterface $container, $name, callable $callback): HttpServer
+    {
+        /** @var HttpServer $server */
         $server = $callback();
         $logger = $container->get(LoggerInterface::class);
 
diff --git a/module/EventDispatcher/src/Async/TaskRunnerFactory.php b/module/EventDispatcher/src/Async/TaskRunnerFactory.php
index 935b6d61..cacfefc5 100644
--- a/module/EventDispatcher/src/Async/TaskRunnerFactory.php
+++ b/module/EventDispatcher/src/Async/TaskRunnerFactory.php
@@ -3,13 +3,12 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\EventDispatcher\Async;
 
-use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerInterface;
 use Psr\Log\LoggerInterface;
-use Zend\ServiceManager\Factory\FactoryInterface;
 
-class TaskRunnerFactory implements FactoryInterface
+class TaskRunnerFactory
 {
-    public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null): TaskRunner
+    public function __invoke(ContainerInterface $container): TaskRunner
     {
         $logger = $container->get(LoggerInterface::class);
         return new TaskRunner($logger, $container);
diff --git a/module/EventDispatcher/src/Listener/ListenerProviderFactory.php b/module/EventDispatcher/src/Listener/ListenerProviderFactory.php
index d40687b9..7e9198a8 100644
--- a/module/EventDispatcher/src/Listener/ListenerProviderFactory.php
+++ b/module/EventDispatcher/src/Listener/ListenerProviderFactory.php
@@ -3,17 +3,16 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\EventDispatcher\Listener;
 
-use Interop\Container\ContainerInterface;
 use Phly\EventDispatcher\ListenerProvider\AttachableListenerProvider;
+use Psr\Container\ContainerInterface;
 use Swoole\Http\Server as HttpServer;
-use Zend\ServiceManager\Factory\FactoryInterface;
 
 use function Phly\EventDispatcher\lazyListener;
 use function Shlinkio\Shlink\EventDispatcher\asyncListener;
 
-class ListenerProviderFactory implements FactoryInterface
+class ListenerProviderFactory
 {
-    public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
+    public function __invoke(ContainerInterface $container)
     {
         $config = $container->has('config') ? $container->get('config') : [];
         $events = $config['events'] ?? [];
diff --git a/module/EventDispatcher/test/Async/TaskRunnerDelegatorTest.php b/module/EventDispatcher/test/Async/TaskRunnerDelegatorTest.php
index 82c6b280..ad0978e7 100644
--- a/module/EventDispatcher/test/Async/TaskRunnerDelegatorTest.php
+++ b/module/EventDispatcher/test/Async/TaskRunnerDelegatorTest.php
@@ -3,8 +3,8 @@ declare(strict_types=1);
 
 namespace ShlinkioTest\Shlink\EventDispatcher\Async;
 
-use Interop\Container\ContainerInterface;
 use PHPUnit\Framework\TestCase;
+use Psr\Container\ContainerInterface;
 use Psr\Log\LoggerInterface;
 use Shlinkio\Shlink\EventDispatcher\Async\TaskRunner;
 use Shlinkio\Shlink\EventDispatcher\Async\TaskRunnerDelegator;
diff --git a/module/EventDispatcher/test/Async/TaskRunnerFactoryTest.php b/module/EventDispatcher/test/Async/TaskRunnerFactoryTest.php
index 418abe29..cf139b62 100644
--- a/module/EventDispatcher/test/Async/TaskRunnerFactoryTest.php
+++ b/module/EventDispatcher/test/Async/TaskRunnerFactoryTest.php
@@ -3,8 +3,8 @@ declare(strict_types=1);
 
 namespace ShlinkioTest\Shlink\EventDispatcher\Async;
 
-use Interop\Container\ContainerInterface;
 use PHPUnit\Framework\TestCase;
+use Psr\Container\ContainerInterface;
 use Psr\Log\LoggerInterface;
 use ReflectionObject;
 use Shlinkio\Shlink\EventDispatcher\Async\TaskRunner;
diff --git a/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php b/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php
index f0c3b47f..493940a3 100644
--- a/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php
+++ b/module/EventDispatcher/test/Listener/ListenerProviderFactoryTest.php
@@ -3,9 +3,9 @@ declare(strict_types=1);
 
 namespace ShlinkioTest\Shlink\EventDispatcher\Listener;
 
-use Interop\Container\ContainerInterface;
 use Phly\EventDispatcher\ListenerProvider\AttachableListenerProvider;
 use PHPUnit\Framework\TestCase;
+use Psr\Container\ContainerInterface;
 use ReflectionObject;
 use Shlinkio\Shlink\EventDispatcher\Listener\ListenerProviderFactory;
 use Swoole\Http\Server as HttpServer;
diff --git a/module/PreviewGenerator/src/Image/ImageBuilderFactory.php b/module/PreviewGenerator/src/Image/ImageBuilderFactory.php
index fca5aa18..402fa228 100644
--- a/module/PreviewGenerator/src/Image/ImageBuilderFactory.php
+++ b/module/PreviewGenerator/src/Image/ImageBuilderFactory.php
@@ -3,29 +3,13 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\PreviewGenerator\Image;
 
-use Interop\Container\ContainerInterface;
-use Interop\Container\Exception\ContainerException;
 use mikehaertl\wkhtmlto\Image;
-use Zend\ServiceManager\Exception\ServiceNotCreatedException;
-use Zend\ServiceManager\Exception\ServiceNotFoundException;
-use Zend\ServiceManager\Factory\FactoryInterface;
+use Psr\Container\ContainerInterface;
 
 /** @deprecated  */
-class ImageBuilderFactory implements FactoryInterface
+class ImageBuilderFactory
 {
-    /**
-     * Create an object
-     *
-     * @param  ContainerInterface $container
-     * @param  string $requestedName
-     * @param  null|array $options
-     * @return object
-     * @throws ServiceNotFoundException if unable to resolve the service.
-     * @throws ServiceNotCreatedException if an exception is raised when
-     *     creating a service.
-     * @throws ContainerException if any other error occurs
-     */
-    public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
+    public function __invoke(ContainerInterface $container)
     {
         return new ImageBuilder($container, ['factories' => [
             Image::class => ImageFactory::class,
diff --git a/module/PreviewGenerator/src/Image/ImageFactory.php b/module/PreviewGenerator/src/Image/ImageFactory.php
index 87dc2a39..bc702205 100644
--- a/module/PreviewGenerator/src/Image/ImageFactory.php
+++ b/module/PreviewGenerator/src/Image/ImageFactory.php
@@ -3,29 +3,13 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\PreviewGenerator\Image;
 
-use Interop\Container\ContainerInterface;
-use Interop\Container\Exception\ContainerException;
 use mikehaertl\wkhtmlto\Image;
-use Zend\ServiceManager\Exception\ServiceNotCreatedException;
-use Zend\ServiceManager\Exception\ServiceNotFoundException;
-use Zend\ServiceManager\Factory\FactoryInterface;
+use Psr\Container\ContainerInterface;
 
 /** @deprecated  */
-class ImageFactory implements FactoryInterface
+class ImageFactory
 {
-    /**
-     * Create an object
-     *
-     * @param  ContainerInterface $container
-     * @param  string $requestedName
-     * @param  null|array $options
-     * @return object
-     * @throws ServiceNotFoundException if unable to resolve the service.
-     * @throws ServiceNotCreatedException if an exception is raised when
-     *     creating a service.
-     * @throws ContainerException if any other error occurs
-     */
-    public function __invoke(ContainerInterface $container, $requestedName, ?array $options = null)
+    public function __invoke(ContainerInterface $container, string $requestedName, ?array $options = null)
     {
         $config = $container->get('config')['wkhtmltopdf'];
         $image = new Image($config['images'] ?? null);
diff --git a/module/Rest/src/Authentication/AuthenticationPluginManagerFactory.php b/module/Rest/src/Authentication/AuthenticationPluginManagerFactory.php
index 5326eee4..b42f4a61 100644
--- a/module/Rest/src/Authentication/AuthenticationPluginManagerFactory.php
+++ b/module/Rest/src/Authentication/AuthenticationPluginManagerFactory.php
@@ -3,7 +3,7 @@ declare(strict_types=1);
 
 namespace Shlinkio\Shlink\Rest\Authentication;
 
-use Interop\Container\ContainerInterface;
+use Psr\Container\ContainerInterface;
 
 class AuthenticationPluginManagerFactory
 {