diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index d61fab61caa575072db7dfc6540d811f17656fe3..41203ac8f640af0d3c0e32dc13701e18cf6c85f1 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -3,7 +3,7 @@ image: docker:19.03.1
 variables:
   DOCKER_TLS_CERTDIR: "/certs"
   IMAGE_TAG: $CI_REGISTRY_IMAGE
-  IMAGE_VER: 0.8.2
+  IMAGE_VER: 0.9.0
 
 services:
   - docker:19.03.1-dind
diff --git a/lib/CF/Controller/Websockets.pm b/lib/CF/Controller/Websockets.pm
index 2ba09b10edde8ffae18bf8ecb35c6f16307c06c2..119cefbf2b0ef5e58501033fcd9b432731a6c54f 100644
--- a/lib/CF/Controller/Websockets.pm
+++ b/lib/CF/Controller/Websockets.pm
@@ -2,17 +2,16 @@ package CF::Controller::Websockets;
 
 use Mojo::Base 'Mojolicious::Controller';
 use Mojo::Pg::PubSub;
-use JSON;
 use Digest::SHA qw(hmac_sha1_hex);
 
 use feature 'signatures';
 no warnings qw{ experimental::signatures };
 
 use constant SOCKET_INACTIVITY_TIMEOUT => 300;
-use constant USER_ALIVE_TIMEOUT        => 100;
 
 sub main {
-    my $c = shift;
+    my $c  = shift;
+    my $ip = $c->tx->remote_address;
 
     $c->inactivity_timeout(SOCKET_INACTIVITY_TIMEOUT);
 
@@ -22,26 +21,35 @@ sub main {
         $c->send($payload);
     });
 
-    $c->on(message => sub( $c, $message ) {
-        my $data = from_json($message);
+    $c->on(json => sub( $c, $message ) {
 
-        if ($data->{payload} =~ /^(\d+)$/) {
-            my $user = $c->schema->resultset('User')->find({ id => $1 });
-            $user->update({keepalive => \'now()'}) if $user;
-        }
-
-        my $min_alive_time = "now() - '" . USER_ALIVE_TIMEOUT. " s'::interval";
+        if ( $message->{event} eq 'KEEPALIVE' ) {
+            my $user_id;
 
-        my $alive = $c->schema->resultset('User')->count(
-            {
-                keepalive => { '>' => \$min_alive_time },
+            if ($message->{payload} =~ /^(\d+)$/) {
+                # TODO: check signtaure
+                $user_id = $1;
             }
-        );
 
-        $c->send(to_json({ event => 'online_users_updated', payload => {
-            all     => $alive,
-            members => $alive,
-        }}));
+            $c->schema->resultset('Socket')->update_or_create({
+                id        => $c->req->headers->header('Sec-WebSocket-Key'),
+                ip        => $ip,
+                keepalive => \'now()',
+                user_id   => $user_id,
+            }, { key => 'primary'} );
+
+            my $all = $c->schema->resultset('Socket_view')->count(
+                { is_alive => 't', }
+            );
+            my $members = $c->schema->resultset('Socket_view')->count(
+                { is_alive => 't', is_member => 't' }
+            );
+
+            $c->send({json => { event => 'online_users_updated', payload => {
+                all     => $all,
+                members => $members,
+            }}});
+        }
 
     });