diff --git a/src/Tgstation.Server.Host/GraphQL/Subscriptions/UserSubscriptions.cs b/src/Tgstation.Server.Host/GraphQL/Subscriptions/UserSubscriptions.cs
new file mode 100644
index 0000000000..b5a8c14998
--- /dev/null
+++ b/src/Tgstation.Server.Host/GraphQL/Subscriptions/UserSubscriptions.cs
@@ -0,0 +1,93 @@
+using System;
+using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
+
+using HotChocolate;
+using HotChocolate.Execution;
+using HotChocolate.Subscriptions;
+using HotChocolate.Types;
+
+using Tgstation.Server.Api.Rights;
+using Tgstation.Server.Host.GraphQL.Types;
+using Tgstation.Server.Host.Models.Transformers;
+using Tgstation.Server.Host.Security;
+
+namespace Tgstation.Server.Host.GraphQL.Subscriptions
+{
+ ///
+ /// Subscriptions for .
+ ///
+ [ExtendObjectType(typeof(Subscription))]
+ public sealed class UserSubscriptions
+ {
+ ///
+ /// The name of the topic for when any user is updated.
+ ///
+ const string UserUpdatedTopic = "UserUpdated";
+
+ ///
+ /// Get the names of the topics to send to when a is updated.
+ ///
+ /// The of the updated .
+ /// An of topic s.
+ public static IEnumerable UserUpdatedTopics(long userId)
+ {
+ yield return UserUpdatedTopic;
+ yield return SpecificUserUpdatedTopic(userId);
+ }
+
+ ///
+ /// The name of the topic for when a specific is updated.
+ ///
+ /// The of the updated .
+ /// The topic .
+ static string SpecificUserUpdatedTopic(long userId)
+ => $"{UserUpdatedTopic}.{userId}";
+
+ ///
+ /// Receive an update for all changes.
+ ///
+ /// The received from the publisher.
+ /// The updated .
+ [Subscribe]
+ [TgsGraphQLAuthorize(AdministrationRights.ReadUsers)]
+ public User UserUpdated([EventMessage] Models.User user)
+ {
+ ArgumentNullException.ThrowIfNull(user);
+
+ return ((Models.IApiTransformable)user).ToApi();
+ }
+
+ ///
+ /// for .
+ ///
+ /// The .
+ /// The for the request.
+ /// The for the operation.
+ /// A resulting in a of the for the .
+ public ValueTask> CurrentUserUpdatedStream(
+ [Service] ITopicEventReceiver receiver,
+ [Service] IAuthenticationContext authenticationContext,
+ CancellationToken cancellationToken)
+ {
+ ArgumentNullException.ThrowIfNull(receiver);
+ ArgumentNullException.ThrowIfNull(authenticationContext);
+ return receiver.SubscribeAsync(SpecificUserUpdatedTopic(Models.ModelExtensions.Require(authenticationContext.User, user => user.Id)), cancellationToken);
+ }
+
+ ///
+ /// Receive an update to the logged in when it is changed.
+ ///
+ /// The received from the publisher.
+ /// The updated .
+ [Subscribe]
+ [TgsGraphQLAuthorize]
+ public User CurrentUserUpdated([EventMessage] Models.User user)
+ {
+ ArgumentNullException.ThrowIfNull(user);
+
+ return ((Models.IApiTransformable)user).ToApi();
+ }
+ }
+}