diff --git a/.env.development.example b/.env.development.example
index 5fe4cab1..77d46b82 100644
--- a/.env.development.example
+++ b/.env.development.example
@@ -3,6 +3,7 @@ ENV=development
 USER_ID=1000
 HTTP_PORT=80
 TIMEZONE="Europe/Berlin"
+MIN_RUNTIME_IN_SECONDS_FOR_JOB_PROCESSING=15
 
 # Database
 DATABASE_HOST="mysql"
diff --git a/.env.production.example b/.env.production.example
index efdaf917..bad5e1d8 100644
--- a/.env.production.example
+++ b/.env.production.example
@@ -1,6 +1,7 @@
 # Enviroment
 ENV=production
 TIMEZONE="Europe/Berlin"
+MIN_RUNTIME_IN_SECONDS_FOR_JOB_PROCESSING=15
 
 # Database
 DATABASE_HOST=
diff --git a/Makefile b/Makefile
index ab8b3961..4d684905 100644
--- a/Makefile
+++ b/Makefile
@@ -82,6 +82,9 @@ app_sync_tmdb:
 app_sync_letterboxd:
 	make exec_app_cmd CMD="php bin/console.php letterboxd:sync $(CSV_PATH)"
 
+app_jobs_process:
+	make exec_app_cmd CMD="php bin/console.php jobs:process"
+
 # Tests
 #######
 test: test_phpcs test_psalm test_phpstan
diff --git a/README.md b/README.md
index 260da452..f0d5537d 100644
--- a/README.md
+++ b/README.md
@@ -10,9 +10,9 @@ Demo installation can be found [here](https://movary-demo.leepeuker.dev/) (login
 2. [Install via docker](#install-via-docker)
 3. [Important: First steps](#important-first-steps)
 4. [Features](#features)
-    1. [Plex Scrobbler](#plex-scrobbler)
-    2. [Trakt.tv Sync](#trakttv-sync)
-    3. [Tmdb Sync](#tmdb-sync)
+    1. [Tmdb Sync](#tmdb-sync)
+    2. [Plex Scrobbler](#plex-scrobbler)
+    3. [Trakt.tv Sync](#trakttv-sync)
 5. [Development](#development)
 
 <a name="#about"></a>
@@ -111,6 +111,10 @@ DATABASE_PASSWORD=
 DATABASE_DRIVER=pdo_mysql
 DATABASE_CHARSET=utf8
 
+# Minimum number of seconds the job processing worker has to run 
+# => the smallest possible timeperiode between processing two jobs
+MIN_RUNTIME_IN_SECONDS_FOR_JOB_PROCESSING=15
+
 # https://www.themoviedb.org/settings/api
 TMDB_API_KEY= 
 
@@ -127,6 +131,26 @@ their [docs](https://dockerfile.readthedocs.io/en/latest/content/DockerImages/do
 
 ## Features
 
+<a name="#tmdb-sync"></a>
+
+### tmdb sync
+
+Update movie (meta) data with themoviedb.org information.
+Make sure you have added the variables `TMDB_API_KEY` to the environment.
+
+Example:
+
+`docker exec movary php bin/console.php tmdb:sync`
+
+**Flags:**
+
+- `--hours`
+  Only movies which were last synced X hours or longer ago will be synced
+- `--threshold`
+  Maximum number of movies to sync
+
+<a name="#development"></a>
+
 <a name="#plex-scrobbler"></a>
 
 ### Plex Scrobbler
@@ -162,26 +186,6 @@ Example (syncing history and ratings for user with id 1):
 - `--ignore-cache`
   Use if you want to sync everything from trakt regardless if there was a change since the last sync.
 
-<a name="#tmdb-sync"></a>
-
-### tmdb sync
-
-Update movie (meta) data with themoviedb.org information.
-Make sure you have added the variables `TMDB_API_KEY` to the environment.
-
-Example:
-
-`docker exec movary php bin/console.php tmdb:sync`
-
-**Flags:**
-
-- `--hours`
-  Only movies which were last synced X hours or longer ago will be synced
-- `--threshold`
-  Maximum number of movies to sync
-
-<a name="#development"></a>
-
 ## Development
 
 ### Setup
diff --git a/bin/console.php b/bin/console.php
index dff65729..39f721ef 100644
--- a/bin/console.php
+++ b/bin/console.php
@@ -13,5 +13,6 @@
 $application->add($container->get(Movary\Command\UserDelete::class));
 $application->add($container->get(Movary\Command\UserUpdate::class));
 $application->add($container->get(Movary\Command\UserList::class));
+$application->add($container->get(Movary\Command\ProcessJobs::class));
 
 $application->run();
diff --git a/bootstrap.php b/bootstrap.php
index 8e79090b..b276d660 100644
--- a/bootstrap.php
+++ b/bootstrap.php
@@ -15,6 +15,7 @@
         \Movary\Command\DatabaseMigrationStatus::class => DI\factory([Factory::class, 'createDatabaseMigrationStatusCommand']),
         \Movary\Command\DatabaseMigrationMigrate::class => DI\factory([Factory::class, 'createDatabaseMigrationMigrateCommand']),
         \Movary\Command\DatabaseMigrationRollback::class => DI\factory([Factory::class, 'createDatabaseMigrationRollbackCommand']),
+        \Movary\Command\ProcessJobs::class => DI\factory([Factory::class, 'createProcessJobCommand']),
         \Psr\Http\Client\ClientInterface::class => DI\factory([Factory::class, 'createHttpClient']),
         \Psr\Log\LoggerInterface::class => DI\factory([Factory::class, 'createFileLogger']),
         \Doctrine\DBAL\Connection::class => DI\factory([Factory::class, 'createDbConnection']),
diff --git a/build/php/Dockerfile b/build/php/Dockerfile
index a7021c03..e8824577 100644
--- a/build/php/Dockerfile
+++ b/build/php/Dockerfile
@@ -9,4 +9,5 @@ ARG APPLICATION_VERSION
 ENV APPLICATION_VERSION=${APPLICATION_VERSION}
 COPY --chown=application ./ ./
 COPY .env.production.example .env
+COPY settings/supervisor/movary.conf /opt/docker/etc/supervisor.d/movary.conf
 RUN composer install --no-dev
diff --git a/db/migrations/20220719134322_AddJobQueueTable.php b/db/migrations/20220719134322_AddJobQueueTable.php
new file mode 100644
index 00000000..eb9abdb4
--- /dev/null
+++ b/db/migrations/20220719134322_AddJobQueueTable.php
@@ -0,0 +1,29 @@
+<?php declare(strict_types=1);
+
+use Phinx\Migration\AbstractMigration;
+
+final class AddJobQueueTable extends AbstractMigration
+{
+    public function down() : void
+    {
+        $this->execute(
+            <<<SQL
+            DROP TABLE `job_queue`
+            SQL
+        );
+    }
+
+    public function up() : void
+    {
+        $this->execute(
+            <<<SQL
+            CREATE TABLE `job_queue` (
+                `id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT,
+                `job` TEXT NOT NULL,
+                `created_at` DATETIME NOT NULL DEFAULT NOW(),
+                PRIMARY KEY (`id`)
+            ) COLLATE="utf8mb4_unicode_ci" ENGINE=InnoDB
+            SQL
+        );
+    }
+}
diff --git a/settings/routes.php b/settings/routes.php
index c6d6f6f0..640318d6 100644
--- a/settings/routes.php
+++ b/settings/routes.php
@@ -132,6 +132,16 @@
         '/user/delete-account',
         [\Movary\HttpController\SettingsController::class, 'deleteAccount']
     );
+    $routeCollector->addRoute(
+        'GET',
+        '/jobs/schedule/trakt-history-sync',
+        [\Movary\HttpController\JobController::class, 'scheduleTraktHistorySync']
+    );
+    $routeCollector->addRoute(
+        'GET',
+        '/jobs/schedule/trakt-ratings-sync',
+        [\Movary\HttpController\JobController::class, 'scheduleTraktRatingsSync']
+    );
     $routeCollector->addRoute(
         'POST',
         '/user/date-format',
diff --git a/settings/supervisor/movary.conf b/settings/supervisor/movary.conf
new file mode 100644
index 00000000..47dbd8a1
--- /dev/null
+++ b/settings/supervisor/movary.conf
@@ -0,0 +1,12 @@
+[program:movary]
+command=/usr/local/bin/php /app/bin/console.php jobs:process
+numprocs=1
+user=application
+autostart=true
+autorestart=true
+startsecs=1
+startretries=10
+stdout_logfile=/dev/stdout
+stdout_logfile_maxbytes=0
+stderr_logfile=/dev/stderr
+stderr_logfile_maxbytes=0
diff --git a/src/Application/Service/Tmdb/SyncMovies.php b/src/Application/Service/Tmdb/SyncMovies.php
index c924f285..626e6b9d 100644
--- a/src/Application/Service/Tmdb/SyncMovies.php
+++ b/src/Application/Service/Tmdb/SyncMovies.php
@@ -19,7 +19,7 @@ public function __construct(
     ) {
     }
 
-    public function syncMovies(?int $maxAgeInHours, ?int $movieCountSyncThreshold) : void
+    public function syncMovies(?int $maxAgeInHours = null, ?int $movieCountSyncThreshold = null) : void
     {
         $movies = $this->movieApi->fetchAllOrderedByLastUpdatedAtTmdbAsc();
 
diff --git a/src/Application/User/Entity.php b/src/Application/User/Entity.php
index e003943d..33943dc5 100644
--- a/src/Application/User/Entity.php
+++ b/src/Application/User/Entity.php
@@ -9,7 +9,7 @@ private function __construct(
         private readonly string $passwordHash,
         private readonly bool $areCoreAccountChangesDisabled,
         private readonly ?string $plexWebhookUuid,
-        private readonly ?string $dateFormat,
+        private readonly ?int $dateFormatId,
         private readonly ?string $TraktUserName,
         private readonly ?string $TraktClientId,
     ) {
@@ -22,7 +22,7 @@ public static function createFromArray(array $data) : self
             $data['password'],
             (bool)$data['core_account_changes_disabled'],
             $data['plex_webhook_uuid'],
-            $data['date_format'],
+            $data['date_format_id'],
             $data['trakt_user_name'],
             $data['trakt_client_id'],
         );
@@ -33,9 +33,9 @@ public function areCoreAccountChangesDisabled() : bool
         return $this->areCoreAccountChangesDisabled;
     }
 
-    public function getDateFormat() : ?string
+    public function getDateFormatId() : ?int
     {
-        return $this->dateFormat;
+        return $this->dateFormatId;
     }
 
     public function getId() : int
diff --git a/src/Command/ProcessJobs.php b/src/Command/ProcessJobs.php
new file mode 100644
index 00000000..924c221d
--- /dev/null
+++ b/src/Command/ProcessJobs.php
@@ -0,0 +1,82 @@
+<?php declare(strict_types=1);
+
+namespace Movary\Command;
+
+use Movary\Worker;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\Console\Input\InputInterface;
+use Symfony\Component\Console\Input\InputOption;
+use Symfony\Component\Console\Output\OutputInterface;
+
+class ProcessJobs extends Command
+{
+    private const OPTION_NAME_MIN_RUNTIME = 'minRuntime';
+
+    protected static $defaultName = 'jobs:process';
+
+    public function __construct(
+        private readonly Worker\Repository $repository,
+        private readonly Worker\Service $workerService,
+        private readonly LoggerInterface $logger,
+        private readonly ?int $minRuntimeInSeconds = null
+    ) {
+        parent::__construct();
+    }
+
+    protected function configure() : void
+    {
+        $this
+            ->setDescription('Process job from the queue.')
+            ->addOption(self::OPTION_NAME_MIN_RUNTIME, 'minRuntime', InputOption::VALUE_REQUIRED, 'Minimum runtime of command.');
+    }
+
+    // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter
+    protected function execute(InputInterface $input, OutputInterface $output) : int
+    {
+        $minRuntime = $input->getOption(self::OPTION_NAME_MIN_RUNTIME) ?? $this->minRuntimeInSeconds;
+
+        $timeStart = microtime(true);
+
+        $this->generateOutput($output, 'Processing job...');
+
+        try {
+            $processedJobType = $this->processJob();
+        } catch (\Exception $e) {
+            $this->logger->error('Could not process job.', ['exception' => $e]);
+
+            return Command::FAILURE;
+        }
+
+        $processedMessage = 'Nothing to process.';
+        if ($processedJobType !== null) {
+            $processedMessage = 'Processed job of type: ' . $processedJobType;
+        }
+
+        $this->generateOutput($output, $processedMessage);
+
+        $missingTime = (int)$minRuntime - (microtime(true) - $timeStart);
+        if ($missingTime > 0) {
+            $waitTime = max((int)ceil($missingTime * 1000000), 0);
+
+            $this->generateOutput($output, 'Sleeping for ' . $waitTime / 1000000 . ' seconds to reach min runtime...');
+
+            usleep($waitTime);
+        }
+
+        return Command::SUCCESS;
+    }
+
+    private function processJob() : ?string
+    {
+        $job = $this->repository->fetchOldestJob();
+
+        if ($job === null) {
+            return null;
+        }
+
+        $this->workerService->processJob($job);
+
+        /** @noinspection PhpUnreachableStatementInspection */
+        return $job->getType();
+    }
+}
diff --git a/src/Factory.php b/src/Factory.php
index ac9136ae..94611138 100644
--- a/src/Factory.php
+++ b/src/Factory.php
@@ -169,4 +169,20 @@ public static function createTwigFilesystemLoader() : Twig\Loader\FilesystemLoad
     {
         return new Twig\Loader\FilesystemLoader(__DIR__ . '/../templates');
     }
+
+    public function createProcessJobCommand(ContainerInterface $container, Config $config) : Command\ProcessJobs
+    {
+        try {
+            $minRuntimeInSeconds = $config->getAsInt('MIN_RUNTIME_IN_SECONDS_FOR_JOB_PROCESSING');
+        } catch (\OutOfBoundsException) {
+            $minRuntimeInSeconds = null;
+        }
+
+        return new Command\ProcessJobs(
+            $container->get(Worker\Repository::class),
+            $container->get(Worker\Service::class),
+            $container->get(LoggerInterface::class),
+            $minRuntimeInSeconds,
+        );
+    }
 }
diff --git a/src/HttpController/JobController.php b/src/HttpController/JobController.php
new file mode 100644
index 00000000..1daa9fe2
--- /dev/null
+++ b/src/HttpController/JobController.php
@@ -0,0 +1,52 @@
+<?php declare(strict_types=1);
+
+namespace Movary\HttpController;
+
+use Movary\Application\User\Service\Authentication;
+use Movary\ValueObject\Http\Header;
+use Movary\ValueObject\Http\Response;
+use Movary\ValueObject\Http\StatusCode;
+use Movary\Worker\Service;
+
+class JobController
+{
+    public function __construct(
+        private readonly Authentication $authenticationService,
+        private readonly Service $workerService
+    ) {
+    }
+
+    public function scheduleTraktHistorySync() : Response
+    {
+        if ($this->authenticationService->isUserAuthenticated() === false) {
+            return Response::createFoundRedirect('/');
+        }
+
+        $this->workerService->addTraktHistorySyncJob($this->authenticationService->getCurrentUserId());
+
+        $_SESSION['scheduledTraktHistorySync'] = true;
+
+        return Response::create(
+            StatusCode::createSeeOther(),
+            null,
+            [Header::createLocation($_SERVER['HTTP_REFERER'])]
+        );
+    }
+
+    public function scheduleTraktRatingsSync() : Response
+    {
+        if ($this->authenticationService->isUserAuthenticated() === false) {
+            return Response::createFoundRedirect('/');
+        }
+
+        $this->workerService->addTraktRatingsSyncJob($this->authenticationService->getCurrentUserId());
+
+        $_SESSION['scheduledTraktRatingsSync'] = true;
+
+        return Response::create(
+            StatusCode::createSeeOther(),
+            null,
+            [Header::createLocation($_SERVER['HTTP_REFERER'])]
+        );
+    }
+}
diff --git a/src/HttpController/SettingsController.php b/src/HttpController/SettingsController.php
index 0a303aa4..113d6b92 100644
--- a/src/HttpController/SettingsController.php
+++ b/src/HttpController/SettingsController.php
@@ -105,6 +105,8 @@ public function render() : Response
         $deletedUserHistory = empty($_SESSION['deletedUserHistory']) === false ? $_SESSION['deletedUserHistory'] : null;
         $deletedUserRatings = empty($_SESSION['deletedUserRatings']) === false ? $_SESSION['deletedUserRatings'] : null;
         $dateFormatUpdated = empty($_SESSION['dateFormatUpdated']) === false ? $_SESSION['dateFormatUpdated'] : null;
+        $scheduledTraktHistorySync = empty($_SESSION['scheduledTraktHistorySync']) === false ? $_SESSION['scheduledTraktHistorySync'] : null;
+        $scheduledTraktRatingsSync = empty($_SESSION['scheduledTraktRatingsSync']) === false ? $_SESSION['scheduledTraktRatingsSync'] : null;
         unset(
             $_SESSION['passwordUpdated'],
             $_SESSION['passwordErrorCurrentInvalid'],
@@ -117,6 +119,8 @@ public function render() : Response
             $_SESSION['deletedUserHistory'],
             $_SESSION['deletedUserRatings'],
             $_SESSION['dateFormatUpdated'],
+            $_SESSION['scheduledTraktHistorySync'],
+            $_SESSION['scheduledTraktRatingsSync'],
         );
 
         $user = $this->userApi->fetchUser($userId);
@@ -126,13 +130,15 @@ public function render() : Response
             $this->twig->render('page/settings.html.twig', [
                 'coreAccountChangesDisabled' => $user->areCoreAccountChangesDisabled(),
                 'dateFormats' => DateFormat::getFormats(),
-                'dateFormatSelected' => $user->getDateFormat(),
+                'dateFormatSelected' => $user->getDateFormatId(),
                 'dateFormatUpdated' => $dateFormatUpdated,
                 'plexWebhookUrl' => $user->getPlexWebhookId() ?? '-',
                 'passwordErrorNotEqual' => $passwordErrorNotEqual,
                 'passwordErrorMinLength' => $passwordErrorMinLength,
                 'passwordErrorCurrentInvalid' => $passwordErrorCurrentInvalid,
                 'traktCredentialsUpdated' => $traktCredentialsUpdated,
+                'traktScheduleHistorySyncSuccessful' => $scheduledTraktHistorySync,
+                'traktScheduleRatingsSyncSuccessful' => $scheduledTraktRatingsSync,
                 'importHistorySuccessful' => $importHistorySuccessful,
                 'importRatingsSuccessful' => $importRatingsSuccessful,
                 'passwordUpdated' => $passwordUpdated,
diff --git a/src/Worker/Job.php b/src/Worker/Job.php
new file mode 100644
index 00000000..5a458e3a
--- /dev/null
+++ b/src/Worker/Job.php
@@ -0,0 +1,84 @@
+<?php declare(strict_types=1);
+
+namespace Movary\Worker;
+
+use Ramsey\Uuid\Uuid;
+
+class Job implements \JsonSerializable
+{
+    private const TYPE_TMDB_SYNC = 'tmdb_sync';
+
+    private const TYPE_TRAKT_SYNC_HISTORY = 'trakt_sync_history';
+
+    private const TYPE_TRAKT_SYNC_RATINGS = 'trakt_sync_ratings';
+
+    private function __construct(
+        private readonly string $uuid,
+        private readonly string $type,
+        private readonly array $parameters
+    ) {
+    }
+
+    public static function createFromArray(array $data) : self
+    {
+        return new self(
+            $data['uuid'],
+            $data['type'],
+            $data['parameters'],
+        );
+    }
+
+    public static function createFromParameters(string $uuid, string $type, array $parameters) : self
+    {
+        return new self($uuid, $type, $parameters);
+    }
+
+    public static function createTmdbSync() : self
+    {
+        return new self((string)Uuid::uuid4(), self::TYPE_TMDB_SYNC, []);
+    }
+
+    public static function createTraktHistorySync(int $userId) : self
+    {
+        return new self((string)Uuid::uuid4(), self::TYPE_TRAKT_SYNC_HISTORY, ['userId' => $userId]);
+    }
+
+    public static function createTraktRatingsSync(int $userId) : self
+    {
+        return new self((string)Uuid::uuid4(), self::TYPE_TRAKT_SYNC_RATINGS, ['userId' => $userId]);
+    }
+
+    public function getParameters() : array
+    {
+        return $this->parameters;
+    }
+
+    public function getType() : string
+    {
+        return $this->type;
+    }
+
+    public function isOfTypeTmdbSync() : bool
+    {
+        return $this->type === self::TYPE_TMDB_SYNC;
+    }
+
+    public function isOfTypeTraktSyncHistory() : bool
+    {
+        return $this->type === self::TYPE_TRAKT_SYNC_HISTORY;
+    }
+
+    public function isOfTypeTraktSyncRankings() : bool
+    {
+        return $this->type === self::TYPE_TRAKT_SYNC_RATINGS;
+    }
+
+    public function jsonSerialize() : array
+    {
+        return [
+            'uuid' => $this->uuid,
+            'type' => $this->type,
+            'parameters' => $this->parameters,
+        ];
+    }
+}
diff --git a/src/Worker/Repository.php b/src/Worker/Repository.php
new file mode 100644
index 00000000..c3c95c20
--- /dev/null
+++ b/src/Worker/Repository.php
@@ -0,0 +1,45 @@
+<?php declare(strict_types=1);
+
+namespace Movary\Worker;
+
+use Doctrine\DBAL\Connection;
+use Movary\Util\Json;
+
+class Repository
+{
+    public function __construct(private readonly Connection $dbConnection)
+    {
+    }
+
+    public function addJob(Job $job) : void
+    {
+        $this->dbConnection->insert(
+            'job_queue',
+            [
+                'job' => Json::encode($job),
+            ]
+        );
+    }
+
+    public function fetchOldestJob() : ?Job
+    {
+        $this->dbConnection->beginTransaction();
+
+        $data = $this->dbConnection->fetchAssociative('SELECT * FROM `job_queue` ORDER BY `created_at` LIMIT 1');
+
+        if ($data === false) {
+            return null;
+        }
+
+        $this->deleteJob($data['id']);
+
+        $this->dbConnection->commit();
+
+        return Job::createFromArray(Json::decode($data['job']));
+    }
+
+    private function deleteJob(int $id) : void
+    {
+        $this->dbConnection->delete('job_queue', ['id' => $id]);
+    }
+}
diff --git a/src/Worker/Service.php b/src/Worker/Service.php
new file mode 100644
index 00000000..a0de9520
--- /dev/null
+++ b/src/Worker/Service.php
@@ -0,0 +1,50 @@
+<?php declare(strict_types=1);
+
+namespace Movary\Worker;
+
+use Movary\Application\Service\Tmdb\SyncMovies;
+use Movary\Application\Service\Trakt;
+
+class Service
+{
+    public function __construct(
+        private readonly Repository $repository,
+        private readonly Trakt\SyncWatchedMovies $traktSyncWatchedMovies,
+        private readonly Trakt\SyncRatings $traktSyncRatings,
+        private readonly SyncMovies $tmdbSyncMovies
+    ) {
+    }
+
+    public function addTmdbSyncJob() : void
+    {
+        $job = Job::createTmdbSync();
+
+        $this->repository->addJob($job);
+    }
+
+    public function addTraktHistorySyncJob(int $userId) : void
+    {
+        $job = Job::createTraktHistorySync($userId);
+
+        $this->repository->addJob($job);
+    }
+
+    public function addTraktRatingsSyncJob(int $userId) : void
+    {
+        $job = Job::createTraktRatingsSync($userId);
+
+        $this->repository->addJob($job);
+    }
+
+    public function processJob(Job $job) : void
+    {
+        $parameters = $job->getParameters();
+
+        match (true) {
+            $job->isOfTypeTraktSyncRankings() => $this->traktSyncRatings->execute($parameters['userId']),
+            $job->isOfTypeTraktSyncHistory() => $this->traktSyncWatchedMovies->execute($parameters['userId']),
+            $job->isOfTypeTmdbSync() => $this->tmdbSyncMovies->syncMovies(),
+            default => throw new \RuntimeException('Job type not supported: ' . $job->getType()),
+        };
+    }
+}
diff --git a/templates/page/settings.html.twig b/templates/page/settings.html.twig
index 61f281f3..28d92324 100644
--- a/templates/page/settings.html.twig
+++ b/templates/page/settings.html.twig
@@ -100,14 +100,24 @@
                 <form action="/user/trakt" method="post">
                     <p style="font-size: 0.8rem;margin-bottom: 0.5rem">Username:</p>
                     <div class="input-group input-group-sm mb-3">
-                        <input type="text" class="form-control" name="traktUserName" placeholder="Enter user name here" value="{{ traktUserName }}"
-                               style="margin-left: 10%;margin-right: 10%;text-align: center;">
+                        <input type="text"
+                               class="form-control"
+                               name="traktUserName"
+                               placeholder="Enter user name here"
+                               value="{{ traktUserName }}"
+                               style="margin-left: 10%;margin-right: 10%;text-align: center;"
+                               {% if coreAccountChangesDisabled == true %}disabled{% endif %}>
                     </div>
 
                     <p style="font-size: 0.8rem;margin-bottom: 0.5rem">Client ID:</p>
                     <div class="input-group input-group-sm mb-3">
-                        <input type="text" class="form-control" name="traktClientId" placeholder="Enter client ID here" value="{{ traktClientId }}"
-                               style="margin-left: 10%;margin-right: 10%;text-align: center;">
+                        <input type="text"
+                               class="form-control"
+                               name="traktClientId"
+                               placeholder="Enter client ID here"
+                               value="{{ traktClientId }} "
+                               style="margin-left: 10%;margin-right: 10%;text-align: center;"
+                               {% if coreAccountChangesDisabled == true %}disabled{% endif %}>
                     </div>
 
                     {% if traktCredentialsUpdated == true %}
@@ -117,8 +127,22 @@
                         </div>
                     {% endif %}
 
-                    <button class="btn btn-primary btn-sm" type="submit">Submit</button>
+                    <button class="btn btn-primary btn-sm" type="submit" {% if coreAccountChangesDisabled == true %}disabled{% endif %}>Submit</button>
                 </form>
+
+                <div style="margin-top: 0.9rem">
+                    <a class="btn btn-warning btn-sm {% if coreAccountChangesDisabled == true or traktUserName is null or traktClientId is null %}disabled{% endif %}"
+                       href="/jobs/schedule/trakt-history-sync">Schedule history sync</a>
+                    <a class="btn btn-warning btn-sm {% if coreAccountChangesDisabled == true or traktUserName is null or traktClientId is null %}disabled{% endif %}"
+                       href="/jobs/schedule/trakt-ratings-sync">Schedule ratings sync</a>
+
+                    {% if traktScheduleHistorySyncSuccessful == true or traktScheduleRatingsSyncSuccessful == true %}
+                        <div class="alert alert-success alert-dismissible" role="alert" style="margin-left: 10%;margin-right: 10%;margin-bottom: 0!important;margin-top: 1rem">
+                            Trakt {% if traktScheduleHistorySyncSuccessful == true %}history{% else %}ratings{% endif %} sync successfully scheduled. Should be processed soon.
+                            <button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
+                        </div>
+                    {% endif %}
+                </div>
             </div>
 
             <hr style="margin: 0;padding: 0">
@@ -143,7 +167,7 @@
                 <form action="/user/import/csv/history" method="post" enctype="multipart/form-data" style="margin-top: 1rem">
                     <div class="input-group input-group-sm">
                         <input type="file" class="form-control" name="history" required>
-                        <button class="btn btn-primary" type="submit">Import history.csv</button>
+                        <button class="btn btn-primary" type="submit" {% if coreAccountChangesDisabled == true %}disabled{% endif %}>Import history.csv</button>
                     </div>
                 </form>
 
@@ -164,7 +188,7 @@
                 <form action="/user/import/csv/ratings" method="post" enctype="multipart/form-data" style="padding-bottom: 0.2rem;margin-top: 1rem">
                     <div class="input-group input-group-sm">
                         <input type="file" class="form-control" name="ratings" required>
-                        <button class="btn btn-primary" type="submit">Import rating.csv</button>
+                        <button class="btn btn-primary" type="submit" {% if coreAccountChangesDisabled == true %}disabled{% endif %}>Import rating.csv</button>
                     </div>
                 </form>
                 {% if importRatingsSuccessful == true %}
@@ -188,8 +212,10 @@
                 <h5 style="margin-bottom: 1rem">Delete your data</h5>
 
                 <div style="margin-bottom: 1rem">
-                    <a class="btn btn-warning btn-sm" href="/user/delete-history" onclick="confirm('Are you sure you want to delete your watch history?')">Delete history</a>
-                    <a class="btn btn-warning btn-sm" href="/user/delete-ratings" onclick="confirm('Are you sure you want to delete your movie ratings?')">Delete ratings</a>
+                    <a class="btn btn-warning btn-sm {% if coreAccountChangesDisabled == true %}disabled{% endif %}" href="/user/delete-history"
+                       onclick="confirm('Are you sure you want to delete your watch history?')">Delete history</a>
+                    <a class="btn btn-warning btn-sm {% if coreAccountChangesDisabled == true %}disabled{% endif %}" href="/user/delete-ratings"
+                       onclick="confirm('Are you sure you want to delete your movie ratings?')">Delete ratings</a>
                     {% if deletedUserHistory == true %}
                         <div class="alert alert-success alert-dismissible" role="alert" style="margin-left: 10%;margin-right: 10%;margin-bottom: 0.7rem!important;margin-top: 1rem">
                             History deleted successfully.