diff --git a/src/app/Handlers/Activesync.php b/src/app/Handlers/Activesync.php
--- a/src/app/Handlers/Activesync.php
+++ b/src/app/Handlers/Activesync.php
@@ -2,26 +2,43 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+use App\Sku;
+
 class Activesync extends \App\Handlers\Base
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
         return \App\User::class;
     }
 
+    /**
+     * Handle entitlement creation event.
+     */
+    public static function entitlementCreated(Entitlement $entitlement): void
+    {
+        if (\config('app.with_ldap')) {
+            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+        }
+    }
+
+    /**
+     * Handle entitlement deletion event.
+     */
+    public static function entitlementDeleted(Entitlement $entitlement): void
+    {
+        if (\config('app.with_ldap')) {
+            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+        }
+    }
+
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
-    public static function metadata(\App\Sku $sku): array
+    public static function metadata(Sku $sku): array
     {
         $data = parent::metadata($sku);
 
@@ -33,8 +50,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/Auth2F.php b/src/app/Handlers/Auth2F.php
--- a/src/app/Handlers/Auth2F.php
+++ b/src/app/Handlers/Auth2F.php
@@ -3,19 +3,28 @@
 namespace App\Handlers;
 
 use App\Entitlement;
+use App\Sku;
 
 class Auth2F extends \App\Handlers\Base
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
         return \App\User::class;
     }
 
+    /**
+     * Handle entitlement creation event.
+     */
+    public static function entitlementCreated(Entitlement $entitlement): void
+    {
+        if (\config('app.with_ldap')) {
+            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+        }
+    }
+
     /**
      * Handle entitlement deletion event.
      */
@@ -26,17 +35,17 @@
             // TODO: This should be an async job
             $sf = new \App\Auth\SecondFactor($entitlement->entitleable);
             $sf->removeFactors();
+
+            if (\config('app.with_ldap')) {
+                \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+            }
         }
     }
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
-    public static function metadata(\App\Sku $sku): array
+    public static function metadata(Sku $sku): array
     {
         $data = parent::metadata($sku);
 
@@ -48,8 +57,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/Base.php b/src/app/Handlers/Base.php
--- a/src/app/Handlers/Base.php
+++ b/src/app/Handlers/Base.php
@@ -3,13 +3,12 @@
 namespace App\Handlers;
 
 use App\Entitlement;
+use App\Sku;
 
 abstract class Base
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -36,13 +35,8 @@
      * Check if the SKU is available to the user. An SKU is available
      * to the user/domain when either it is active or there's already an
      * active entitlement.
-     *
-     * @param \App\Sku  $sku    The SKU
-     * @param object    $object The entitleable object
-     *
-     * @return bool
      */
-    public static function isAvailable(\App\Sku $sku, $object): bool
+    public static function isAvailable(Sku $sku, $object): bool
     {
         if (!$sku->active) {
             if (!$object->entitlements()->where('sku_id', $sku->id)->first()) {
@@ -55,12 +49,8 @@
 
     /**
      * Metadata of this SKU handler.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
-    public static function metadata(\App\Sku $sku): array
+    public static function metadata(Sku $sku): array
     {
         return [
             // entitleable type
@@ -78,13 +68,8 @@
 
     /**
      * Prerequisites for the Entitlement to be applied to the object.
-     *
-     * @param \App\Entitlement $entitlement
-     * @param mixed $object
-     *
-     * @return bool
      */
-    public static function preReq($entitlement, $object): bool
+    public static function preReq(Entitlement $entitlement, $object): bool
     {
         $type = static::entitleableClass();
 
@@ -109,8 +94,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/Beta.php b/src/app/Handlers/Beta.php
--- a/src/app/Handlers/Beta.php
+++ b/src/app/Handlers/Beta.php
@@ -2,12 +2,12 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+
 class Beta extends \App\Handlers\Base
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,13 +16,8 @@
 
     /**
      * Prerequisites for the Entitlement to be applied to the object.
-     *
-     * @param \App\Entitlement $entitlement
-     * @param mixed $object
-     *
-     * @return bool
      */
-    public static function preReq($entitlement, $object): bool
+    public static function preReq(Entitlement $entitlement, $object): bool
     {
         // We allow inactive "beta" Sku to be assigned
 
@@ -37,8 +32,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/Domain.php b/src/app/Handlers/Domain.php
--- a/src/app/Handlers/Domain.php
+++ b/src/app/Handlers/Domain.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
diff --git a/src/app/Handlers/DomainHosting.php b/src/app/Handlers/DomainHosting.php
--- a/src/app/Handlers/DomainHosting.php
+++ b/src/app/Handlers/DomainHosting.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,10 +14,6 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
     public static function metadata(\App\Sku $sku): array
     {
diff --git a/src/app/Handlers/DomainRegistration.php b/src/app/Handlers/DomainRegistration.php
--- a/src/app/Handlers/DomainRegistration.php
+++ b/src/app/Handlers/DomainRegistration.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
diff --git a/src/app/Handlers/DomainRelay.php b/src/app/Handlers/DomainRelay.php
--- a/src/app/Handlers/DomainRelay.php
+++ b/src/app/Handlers/DomainRelay.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
diff --git a/src/app/Handlers/Group.php b/src/app/Handlers/Group.php
--- a/src/app/Handlers/Group.php
+++ b/src/app/Handlers/Group.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,10 +14,6 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
     public static function metadata(\App\Sku $sku): array
     {
diff --git a/src/app/Handlers/GroupRoom.php b/src/app/Handlers/GroupRoom.php
--- a/src/app/Handlers/GroupRoom.php
+++ b/src/app/Handlers/GroupRoom.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,10 +14,6 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
     public static function metadata(\App\Sku $sku): array
     {
diff --git a/src/app/Handlers/Groupware.php b/src/app/Handlers/Groupware.php
--- a/src/app/Handlers/Groupware.php
+++ b/src/app/Handlers/Groupware.php
@@ -2,23 +2,41 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+
 class Groupware extends \App\Handlers\Base
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
         return \App\User::class;
     }
 
+    /**
+     * Handle entitlement creation event.
+     */
+    public static function entitlementCreated(Entitlement $entitlement): void
+    {
+        if (\config('app.with_ldap')) {
+            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+        }
+    }
+
+    /**
+     * Handle entitlement deletion event.
+     */
+    public static function entitlementDeleted(Entitlement $entitlement): void
+    {
+        if (\config('app.with_ldap')) {
+            \App\Jobs\User\UpdateJob::dispatch($entitlement->entitleable_id);
+        }
+    }
+
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/Mailbox.php b/src/app/Handlers/Mailbox.php
--- a/src/app/Handlers/Mailbox.php
+++ b/src/app/Handlers/Mailbox.php
@@ -2,6 +2,9 @@
 
 namespace App\Handlers;
 
+use App\Entitlement;
+use App\Sku;
+
 class Mailbox extends \App\Handlers\Base
 {
     /**
@@ -16,12 +19,8 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
-    public static function metadata(\App\Sku $sku): array
+    public static function metadata(Sku $sku): array
     {
         $data = parent::metadata($sku);
 
@@ -35,8 +34,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/Resource.php b/src/app/Handlers/Resource.php
--- a/src/app/Handlers/Resource.php
+++ b/src/app/Handlers/Resource.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,10 +14,6 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
     public static function metadata(\App\Sku $sku): array
     {
diff --git a/src/app/Handlers/Room.php b/src/app/Handlers/Room.php
--- a/src/app/Handlers/Room.php
+++ b/src/app/Handlers/Room.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,10 +14,6 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
     public static function metadata(\App\Sku $sku): array
     {
@@ -34,8 +28,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/app/Handlers/SharedFolder.php b/src/app/Handlers/SharedFolder.php
--- a/src/app/Handlers/SharedFolder.php
+++ b/src/app/Handlers/SharedFolder.php
@@ -6,8 +6,6 @@
 {
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -16,10 +14,6 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
     public static function metadata(\App\Sku $sku): array
     {
diff --git a/src/app/Handlers/Storage.php b/src/app/Handlers/Storage.php
--- a/src/app/Handlers/Storage.php
+++ b/src/app/Handlers/Storage.php
@@ -3,6 +3,7 @@
 namespace App\Handlers;
 
 use App\Entitlement;
+use App\Sku;
 
 class Storage extends \App\Handlers\Base
 {
@@ -11,8 +12,6 @@
 
     /**
      * The entitleable class for this handler.
-     *
-     * @return string
      */
     public static function entitleableClass(): string
     {
@@ -39,12 +38,8 @@
 
     /**
      * SKU handler metadata.
-     *
-     * @param \App\Sku $sku The SKU object
-     *
-     * @return array
      */
-    public static function metadata(\App\Sku $sku): array
+    public static function metadata(Sku $sku): array
     {
         $data = parent::metadata($sku);
 
@@ -62,8 +57,6 @@
     /**
      * The priority that specifies the order of SKUs in UI.
      * Higher number means higher on the list.
-     *
-     * @return int
      */
     public static function priority(): int
     {
diff --git a/src/tests/Feature/EntitlementTest.php b/src/tests/Feature/EntitlementTest.php
--- a/src/tests/Feature/EntitlementTest.php
+++ b/src/tests/Feature/EntitlementTest.php
@@ -41,48 +41,87 @@
 
     /**
      * Tests for EntitlementObserver
-     *
-     * @group skipci
      */
     public function testEntitlementObserver(): void
     {
         $skuStorage = Sku::withEnvTenantContext()->where('title', 'storage')->first();
         $skuMailbox = Sku::withEnvTenantContext()->where('title', 'mailbox')->first();
+        $skuGroupware = Sku::withEnvTenantContext()->where('title', 'groupware')->first();
+        $skuActivesync = Sku::withEnvTenantContext()->where('title', 'activesync')->first();
+        $sku2FA = Sku::withEnvTenantContext()->where('title', '2fa')->first();
+        $skuBeta = Sku::withEnvTenantContext()->where('title', 'beta')->first();
         $user = $this->getTestUser('entitlement-test@kolabnow.com');
         $wallet = $user->wallets->first();
 
-        // Test dispatching update jobs for the user, on quota update
+        $assertPushedUserUpdateJob = function ($ifLdap = false) use ($user) {
+            if ($ifLdap && !\config('app.with_ldap')) {
+                Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
+                return;
+            }
+
+            Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 1);
+            Queue::assertPushed(
+                \App\Jobs\User\UpdateJob::class,
+                function ($job) use ($user) {
+                    return $user->id === TestCase::getObjectProperty($job, 'userId');
+                }
+            );
+        };
+
+        // Note: This also is testing SKU handlers
+
+        // 'mailbox' SKU should not dispatch update jobs
         $this->fakeQueueReset();
         $user->assignSku($skuMailbox, 1, $wallet);
         Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
+        $this->fakeQueueReset();
+        $user->entitlements()->where('sku_id', $skuMailbox->id)->first()->delete();
+        Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
 
+        // Test dispatching update jobs for the user - 'storage' SKU
         $this->fakeQueueReset();
         $user->assignSku($skuStorage, 1, $wallet);
-        Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 1);
-        Queue::assertPushed(
-            \App\Jobs\User\UpdateJob::class,
-            function ($job) use ($user) {
-                return $user->id === TestCase::getObjectProperty($job, 'userId');
-            }
-        );
+        $assertPushedUserUpdateJob();
+        $this->fakeQueueReset();
+        $user->entitlements()->where('sku_id', $skuStorage->id)->first()->delete();
+        $assertPushedUserUpdateJob();
 
+        // Test dispatching update jobs for the user - 'groupware' SKU
         $this->fakeQueueReset();
-        $user->entitlements()->where('sku_id', $skuMailbox->id)->first()->delete();
-        //FIXME this sometimes gives 1?
-        Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
+        $user->assignSku($skuGroupware, 1, $wallet);
+        $assertPushedUserUpdateJob(true);
+        $this->fakeQueueReset();
+        $user->entitlements()->where('sku_id', $skuGroupware->id)->first()->delete();
+        $assertPushedUserUpdateJob(true);
 
+        // Test dispatching update jobs for the user - 'activesync' SKU
         $this->fakeQueueReset();
-        $user->entitlements()->where('sku_id', $skuStorage->id)->first()->delete();
-        //FIXME this sometimes gives 2?
-        Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 1);
-        Queue::assertPushed(
-            \App\Jobs\User\UpdateJob::class,
-            function ($job) use ($user) {
-                return $user->id === TestCase::getObjectProperty($job, 'userId');
-            }
-        );
+        $user->assignSku($skuActivesync, 1, $wallet);
+        $assertPushedUserUpdateJob(true);
+        $this->fakeQueueReset();
+        $user->entitlements()->where('sku_id', $skuActivesync->id)->first()->delete();
+        $assertPushedUserUpdateJob(true);
+
+        // Test dispatching update jobs for the user - '2fa' SKU
+        $this->fakeQueueReset();
+        $user->assignSku($sku2FA, 1, $wallet);
+        $assertPushedUserUpdateJob(true);
+        $this->fakeQueueReset();
+        $user->entitlements()->where('sku_id', $sku2FA->id)->first()->delete();
+        $assertPushedUserUpdateJob(true);
+
+        // Beta SKU should not trigger a user update job
+        $this->fakeQueueReset();
+        $user->assignSku($skuBeta, 1, $wallet);
+        Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
+        $this->fakeQueueReset();
+        $user->entitlements()->where('sku_id', $skuBeta->id)->first()->delete();
+        Queue::assertPushed(\App\Jobs\User\UpdateJob::class, 0);
 
-        // TODO: Test all events in the observer in more detail
+        // TODO: Assert 'creating' checks
+        // TODO: Assert transaction records being created
+        // TODO: Assert timestamps not updated on delete
+        $this->markTestIncomplete();
     }
 
     /**