diff --git a/client/src/app/app.routes.ts b/client/src/app/app.routes.ts
index ceed17c165e468ddab1ffdaa5d6737dbc7a80426..601f051a9250e9e154834950cb6f053047c9e05b 100644
--- a/client/src/app/app.routes.ts
+++ b/client/src/app/app.routes.ts
@@ -20,8 +20,8 @@ export const routes: Routes = [
                 loadComponent: async () => (await import('@app/pages/game/create-game-page/create-game.component')).CreateGamePageComponent,
             },
             {
-                path: 'wait',
-                loadComponent: async () => (await import('@app/pages/game/wait-page/wait-page.component')).WaitPageComponent,
+                path: 'lobby',
+                loadComponent: async () => (await import('@app/pages/game/lobby-page/lobby-page.component')).LobbyPageComponent,
             },
             {
                 path: 'play',
diff --git a/client/src/app/components/topbar/playing-actions/playing-actions.component.html b/client/src/app/components/topbar/playing-actions/playing-actions.component.html
index 0259f0c9c7fe1fe0ff3ee4b304e9ff91e44c4f0d..f34a1384928bdb609a7f2f5068c6cefa10339d49 100644
--- a/client/src/app/components/topbar/playing-actions/playing-actions.component.html
+++ b/client/src/app/components/topbar/playing-actions/playing-actions.component.html
@@ -1,3 +1,3 @@
-<button mat-icon-button routerLink="/home" matTooltip="Abandonner la partie">
+<button mat-icon-button (click)="leave()" matTooltip="Abandonner la partie">
     <mat-icon>logout</mat-icon>
 </button>
diff --git a/client/src/app/components/topbar/playing-actions/playing-actions.component.spec.ts b/client/src/app/components/topbar/playing-actions/playing-actions.component.spec.ts
index fc6e456366f6243befa0368da08c1c837cb8c0ae..ef1bca4c576e8b0c921ffffe58c389259d535dbb 100644
--- a/client/src/app/components/topbar/playing-actions/playing-actions.component.spec.ts
+++ b/client/src/app/components/topbar/playing-actions/playing-actions.component.spec.ts
@@ -1,19 +1,29 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-
 import { PlayingActionsComponent } from './playing-actions.component';
-import { ActivatedRoute } from '@angular/router';
+import { Router } from '@angular/router';
+import { GameService } from '@app/services/game.service';
 
 describe('PlayingActionsComponent', () => {
     let component: PlayingActionsComponent;
     let fixture: ComponentFixture<PlayingActionsComponent>;
 
+    let gameService: jasmine.SpyObj<GameService>;
+    let router: jasmine.SpyObj<Router>;
+
     beforeEach(() => {
+        gameService = jasmine.createSpyObj('GameService', ['leave']);
+        router = jasmine.createSpyObj('Router', ['navigate']);
+
         TestBed.configureTestingModule({
             imports: [PlayingActionsComponent],
             providers: [
                 {
-                    provide: ActivatedRoute,
-                    useValue: {},
+                    provide: GameService,
+                    useValue: gameService,
+                },
+                {
+                    provide: Router,
+                    useValue: router,
                 },
             ],
         });
@@ -25,4 +35,16 @@ describe('PlayingActionsComponent', () => {
     it('should create', () => {
         expect(component).toBeTruthy();
     });
+
+    describe('leave', () => {
+        it('should call gameService.leave', () => {
+            component.leave();
+            expect(gameService.leave).toHaveBeenCalled();
+        });
+
+        it('should navigate to /game/create', () => {
+            component.leave();
+            expect(router.navigate).toHaveBeenCalledWith(['/', 'game', 'create']);
+        });
+    });
 });
diff --git a/client/src/app/components/topbar/playing-actions/playing-actions.component.ts b/client/src/app/components/topbar/playing-actions/playing-actions.component.ts
index eb866167d32b4c94fb2e2649769e2ba3e909d543..816b77ec5d44347c387daca3026f3b9508676fe4 100644
--- a/client/src/app/components/topbar/playing-actions/playing-actions.component.ts
+++ b/client/src/app/components/topbar/playing-actions/playing-actions.component.ts
@@ -1,14 +1,25 @@
 import { Component } from '@angular/core';
-import { RouterLink } from '@angular/router';
+import { Router } from '@angular/router';
 import { MatButtonModule } from '@angular/material/button';
 import { MatIconModule } from '@angular/material/icon';
 import { MatTooltipModule } from '@angular/material/tooltip';
+import { GameService } from '@app/services/game.service';
 
 @Component({
     selector: 'app-playing-actions',
     standalone: true,
-    imports: [RouterLink, MatButtonModule, MatIconModule, MatTooltipModule],
+    imports: [MatButtonModule, MatIconModule, MatTooltipModule],
     templateUrl: './playing-actions.component.html',
     styleUrls: ['./playing-actions.component.scss'],
 })
-export class PlayingActionsComponent {}
+export class PlayingActionsComponent {
+    constructor(
+        private gameService: GameService,
+        private router: Router,
+    ) {}
+
+    leave(): void {
+        this.gameService.leave();
+        this.router.navigate(['/', 'game', 'create']);
+    }
+}
diff --git a/client/src/app/components/topbar/topbar.component.ts b/client/src/app/components/topbar/topbar.component.ts
index aefeff197ab63a2202af07a65baca2d912b0a485..af5f328aa7b45a09321f54af15d04aed81197b0d 100644
--- a/client/src/app/components/topbar/topbar.component.ts
+++ b/client/src/app/components/topbar/topbar.component.ts
@@ -23,7 +23,7 @@ export class TopbarComponent {
     }
 
     isPlayingPage(): boolean {
-        return this.router.url === '/game/play';
+        return this.router.url === '/game/play' || this.router.url === '/game/lobby';
     }
 
     showHomeButton(): boolean {
diff --git a/client/src/app/pages/game/wait-page/wait-page.component.html b/client/src/app/pages/game/lobby-page/lobby-page.component.html
similarity index 100%
rename from client/src/app/pages/game/wait-page/wait-page.component.html
rename to client/src/app/pages/game/lobby-page/lobby-page.component.html
diff --git a/client/src/app/pages/game/wait-page/wait-page.component.scss b/client/src/app/pages/game/lobby-page/lobby-page.component.scss
similarity index 100%
rename from client/src/app/pages/game/wait-page/wait-page.component.scss
rename to client/src/app/pages/game/lobby-page/lobby-page.component.scss
diff --git a/client/src/app/pages/game/wait-page/wait-page.component.spec.ts b/client/src/app/pages/game/lobby-page/lobby-page.component.spec.ts
similarity index 84%
rename from client/src/app/pages/game/wait-page/wait-page.component.spec.ts
rename to client/src/app/pages/game/lobby-page/lobby-page.component.spec.ts
index 7a7bf6253a36e878c5d0596a16e4f68b732b8efc..6b219052d5cbba8416c76ffad746b4466b734f08 100644
--- a/client/src/app/pages/game/wait-page/wait-page.component.spec.ts
+++ b/client/src/app/pages/game/lobby-page/lobby-page.component.spec.ts
@@ -1,12 +1,12 @@
 import { ComponentFixture, TestBed } from '@angular/core/testing';
-import { WaitPageComponent } from './wait-page.component';
+import { LobbyPageComponent } from './lobby-page.component';
 import { Game } from '@common/game';
 import { GameService } from '@app/services/game.service';
 import { Router } from '@angular/router';
 
-describe('WaitPageComponent', () => {
-    let component: WaitPageComponent;
-    let fixture: ComponentFixture<WaitPageComponent>;
+describe('LobbyPageComponent', () => {
+    let component: LobbyPageComponent;
+    let fixture: ComponentFixture<LobbyPageComponent>;
 
     let gameService: jasmine.SpyObj<GameService>;
     let router: jasmine.SpyObj<Router>;
@@ -16,7 +16,7 @@ describe('WaitPageComponent', () => {
         router = jasmine.createSpyObj('Router', ['navigate']);
 
         TestBed.configureTestingModule({
-            imports: [WaitPageComponent],
+            imports: [LobbyPageComponent],
             providers: [
                 {
                     provide: GameService,
@@ -28,7 +28,7 @@ describe('WaitPageComponent', () => {
                 },
             ],
         });
-        fixture = TestBed.createComponent(WaitPageComponent);
+        fixture = TestBed.createComponent(LobbyPageComponent);
         component = fixture.componentInstance;
 
         component.game = {} as Game;
diff --git a/client/src/app/pages/game/wait-page/wait-page.component.ts b/client/src/app/pages/game/lobby-page/lobby-page.component.ts
similarity index 80%
rename from client/src/app/pages/game/wait-page/wait-page.component.ts
rename to client/src/app/pages/game/lobby-page/lobby-page.component.ts
index a0ec0af8d6456c21ebe9ddcb47e239f4a7261922..0ee218ebccbe5c7b41d07f9c096d166542719e79 100644
--- a/client/src/app/pages/game/wait-page/wait-page.component.ts
+++ b/client/src/app/pages/game/lobby-page/lobby-page.component.ts
@@ -7,13 +7,13 @@ import { GameService } from '@app/services/game.service';
 import { Game } from '@common/game';
 
 @Component({
-    selector: 'app-wait-page',
+    selector: 'app-lobby-page',
     standalone: true,
     imports: [AsyncPipe, MatCardModule, MatDividerModule],
-    templateUrl: './wait-page.component.html',
-    styleUrls: ['./wait-page.component.scss'],
+    templateUrl: './lobby-page.component.html',
+    styleUrls: ['./lobby-page.component.scss'],
 })
-export class WaitPageComponent implements OnInit {
+export class LobbyPageComponent implements OnInit {
     game: Game = this.gameService.game;
 
     constructor(
diff --git a/client/src/app/services/game.service.spec.ts b/client/src/app/services/game.service.spec.ts
index a48cffa8dbb8947974baf5318e287c77536bed36..d497ea79906196685ae0a4f0f7c7a2d41dcf0227 100644
--- a/client/src/app/services/game.service.spec.ts
+++ b/client/src/app/services/game.service.spec.ts
@@ -61,7 +61,7 @@ describe('GameService', () => {
 
             await callback(game);
 
-            expect(router.navigate).toHaveBeenCalledWith(['/', 'game', 'wait']);
+            expect(router.navigate).toHaveBeenCalledWith(['/', 'game', 'lobby']);
         });
     });
 
@@ -124,4 +124,12 @@ describe('GameService', () => {
             expect(gameSocketService.send).toHaveBeenCalledWith(GameClientEvent.Demo, quizId);
         });
     });
+
+    describe('leave', () => {
+        it('should send a leave event', () => {
+            service.leave();
+
+            expect(gameSocketService.send).toHaveBeenCalledWith(GameClientEvent.Leave);
+        });
+    });
 });
diff --git a/client/src/app/services/game.service.ts b/client/src/app/services/game.service.ts
index d6b85312f1b81bd7022bb57b80679cf2e28afd84..f179833b97b81c9db665fef3a73f2b95f869b1bb 100644
--- a/client/src/app/services/game.service.ts
+++ b/client/src/app/services/game.service.ts
@@ -19,7 +19,7 @@ export class GameService {
     setupWaitingRoomListener(): void {
         this.gameSocketService.on(GameServerEvent.RedirectToWaitingRoom, async (game: Game) => {
             this.game = game;
-            await this.router.navigate(['/', 'game', 'wait']);
+            await this.router.navigate(['/', 'game', 'lobby']);
         });
     }
 
@@ -43,4 +43,8 @@ export class GameService {
         // eslint-disable-next-line no-underscore-dangle -- mongodb
         this.gameSocketService.send(GameClientEvent.Demo, quiz._id);
     }
+
+    leave(): void {
+        this.gameSocketService.send(GameClientEvent.Leave);
+    }
 }
diff --git a/common/events/game.events.ts b/common/events/game.events.ts
index 93af3d60611001e3075e7dd4418f30aa9190fb53..e15435d06e1fae6e8f040d4e899d7225dba59b21 100644
--- a/common/events/game.events.ts
+++ b/common/events/game.events.ts
@@ -12,6 +12,7 @@ export enum GameClientEvent {
     Create = 'create',
     Demo = 'demo',
     Answer = 'answer',
+    Leave = 'leave',
 }
 
 export type GameEvent = GameServerEvent | GameClientEvent;
diff --git a/server/app/game/classes/room.class.spec.ts b/server/app/game/classes/room.class.spec.ts
index 4e1dfdf922e47b3f51b7b480075eacc498591ef1..b2d4a29a988538119219a26cf3eeef77c679a66d 100644
--- a/server/app/game/classes/room.class.spec.ts
+++ b/server/app/game/classes/room.class.spec.ts
@@ -6,10 +6,13 @@ import type { DefaultEventsMap } from 'socket.io/dist/typed-events';
 import * as sinon from 'sinon';
 import { QuestionType } from '@common/question';
 import { WsException } from '@nestjs/websockets';
+import { Writeable } from '@app/core/types/testing';
 
 jest.useFakeTimers();
 
 describe('Room', () => {
+    let room: Room;
+
     let server: sinon.SinonStubbedInstance<Server>;
     let serverRoom: sinon.SinonStubbedInstance<Socket>;
 
@@ -17,22 +20,35 @@ describe('Room', () => {
         server = sinon.createStubInstance<Server>(Server);
         serverRoom = sinon.createStubInstance<Socket>(Socket);
         server.to.callsFake(() => serverRoom as unknown as BroadcastOperator<DefaultEventsMap, unknown>);
+
+        room = new Room(
+            { id: 'gameid' } as Game,
+            {
+                questions: [
+                    {
+                        type: QuestionType.Qcm,
+                        choices: [
+                            { text: 'choice1', isCorrect: true },
+                            { text: 'choice2', isCorrect: false },
+                        ],
+                    },
+                ],
+            } as unknown as Quiz,
+            server,
+        );
     });
 
     it('should be defined', () => {
-        const room = new Room({} as Game, {} as Quiz, server);
         expect(room).toBeDefined();
     });
 
     describe('addPlayer', () => {
         it('should add a player', () => {
-            const room = new Room({} as Game, {} as Quiz, server);
-
             const client = sinon.createStubInstance(Socket);
 
             room.addPlayer(client, 'player1');
 
-            expect(client.join.calledOnceWithExactly(room.id)).toBe(true);
+            expect(client.join.calledOnceWithExactly(room.game.id)).toBe(true);
 
             const players = room['players'];
             expect(players.size).toBe(1);
@@ -40,9 +56,24 @@ describe('Room', () => {
         });
     });
 
+    describe('removePlayer', () => {
+        it('should remove a player', () => {
+            const client = sinon.createStubInstance(Socket);
+            (client as Writeable<Socket>).id = 'playerid';
+            room['players'].set(client.id, { username: 'player1', score: 0 });
+
+            room.removePlayer(client);
+
+            expect(client.leave.calledOnceWithExactly(room.game.id)).toBe(true);
+
+            const players = room['players'];
+            expect(players.size).toBe(0);
+            expect(players.get(client.id)).toBeUndefined();
+        });
+    });
+
     describe('start', () => {
         it('should start the game after 3 seconds', () => {
-            const room = new Room({} as Game, {} as Quiz, server);
             const nextSpy = sinon.stub(room, 'next');
 
             room.start();
@@ -56,25 +87,9 @@ describe('Room', () => {
     });
 
     describe('next', () => {
-        let room: Room;
         let timesUpStub: sinon.SinonStub;
 
         beforeEach(() => {
-            room = new Room(
-                { id: 'gameid' } as Game,
-                {
-                    questions: [
-                        {
-                            type: QuestionType.Qcm,
-                            choices: [
-                                { text: 'choice1', isCorrect: true },
-                                { text: 'choice2', isCorrect: false },
-                            ],
-                        },
-                    ],
-                } as unknown as Quiz,
-                server,
-            );
             room['currentQuestionIndex'] = -1;
 
             timesUpStub = sinon.stub(room, 'timesUp');
@@ -130,7 +145,6 @@ describe('Room', () => {
     });
 
     describe('answer', () => {
-        let room: Room;
         let sendResultsStub: sinon.SinonStub;
 
         beforeEach(() => {
@@ -181,28 +195,29 @@ describe('Room', () => {
 
     describe('timesUp', () => {
         it('should emit TimesUp', () => {
-            const room = new Room({} as Game, {} as Quiz, server);
-
             room['currentQuestionIndex'] = 0;
 
             room.timesUp();
-            expect(server.to.calledOnceWith(room.id)).toBe(true);
+            expect(server.to.calledOnceWith(room.game.id)).toBe(true);
             expect(serverRoom.emit.calledOnceWith('times-up')).toBe(true);
         });
     });
 
     describe('sendResults', () => {
-        let room: Room;
         let nextStub: sinon.SinonStub;
 
         beforeEach(() => {
-            room = new Room(
-                {} as Game,
-                {
-                    questions: [{ type: QuestionType.Qcm, points: 100, choices: [{ isCorrect: true }, { isCorrect: false }, { isCorrect: true }] }],
-                } as unknown as Quiz,
-                server,
-            );
+            room['quiz'].questions[0] = {
+                _id: 'questionid',
+                type: QuestionType.Qcm,
+                text: 'question',
+                points: 100,
+                choices: [
+                    { isCorrect: true, text: '1' },
+                    { isCorrect: false, text: '2' },
+                    { isCorrect: true, text: '3' },
+                ],
+            };
             room['currentQuestionIndex'] = 0;
             room['players'] = new Map([
                 ['playerid1', { username: 'player1', score: 10 }],
@@ -215,7 +230,7 @@ describe('Room', () => {
         it('should emit the solution with a QCM', () => {
             room.sendResults();
 
-            expect(server.to.calledOnceWith(room.id)).toBe(true);
+            expect(server.to.calledOnceWith(room.game.id)).toBe(true);
             expect(serverRoom.emit.calledOnce).toBe(true);
             expect(serverRoom.emit.calledOnceWith('results')).toBe(true);
 
@@ -235,7 +250,7 @@ describe('Room', () => {
 
             room.sendResults();
 
-            expect(server.to.calledOnceWith(room.id)).toBe(true);
+            expect(server.to.calledOnceWith(room.game.id)).toBe(true);
             expect(serverRoom.emit.calledOnce).toBe(true);
             expect(serverRoom.emit.calledOnceWith('results')).toBe(true);
 
@@ -265,10 +280,8 @@ describe('Room', () => {
 
     describe('end', () => {
         it('should emit EndGame', () => {
-            const room = new Room({} as Game, {} as Quiz, server);
-
             room.end();
-            expect(server.to.calledOnceWith(room.id)).toBe(true);
+            expect(server.to.calledOnceWith(room.game.id)).toBe(true);
             expect(serverRoom.emit.calledOnceWith('end-game')).toBe(true);
         });
     });
diff --git a/server/app/game/classes/room.class.ts b/server/app/game/classes/room.class.ts
index 13ffe34c2a440c3cca7bc9cd4608d42ec9074c81..86c8581899ab5616df59abf4d010f1307ea1c348 100644
--- a/server/app/game/classes/room.class.ts
+++ b/server/app/game/classes/room.class.ts
@@ -9,8 +9,6 @@ import { DELAY_BETWEEN_QUESTIONS_MS, S_TO_MS, BONUS_FACTOR } from './room.class.
 import { WsException } from '@nestjs/websockets';
 
 export class Room {
-    readonly id: string;
-
     private players: Map<string, Player> = new Map();
 
     private currentQuestionIndex: number;
@@ -20,9 +18,7 @@ export class Room {
         readonly game: Game,
         private readonly quiz: Quiz,
         private readonly server: Server,
-    ) {
-        this.id = game.id;
-    }
+    ) {}
 
     addPlayer(client: Socket, username: string) {
         client.join(this.game.id);
@@ -30,6 +26,12 @@ export class Room {
         this.players.set(client.id, { username, score: 0 });
     }
 
+    removePlayer(client: Socket) {
+        client.leave(this.game.id);
+
+        this.players.delete(client.id);
+    }
+
     start() {
         this.currentQuestionIndex = -1;
 
diff --git a/server/app/game/game.gateway.spec.ts b/server/app/game/game.gateway.spec.ts
index 26e75469dbf59000825c02714f9e014f5aa64b21..8052519f929e56fb6e98fad81e0341de4d12ec0b 100644
--- a/server/app/game/game.gateway.spec.ts
+++ b/server/app/game/game.gateway.spec.ts
@@ -2,7 +2,7 @@ import { Test, TestingModule } from '@nestjs/testing';
 import { GameGateway } from './game.gateway';
 import * as sinon from 'sinon';
 import { Socket, Server, BroadcastOperator } from 'socket.io';
-import { GameType } from '@common/game';
+import { Game, GameType } from '@common/game';
 import { QuizDocument } from '@app/quiz/schemas/quiz.schema';
 import { Logger } from '@nestjs/common';
 import { GameRoomService } from './game-room.service';
@@ -50,37 +50,55 @@ describe('GameGateway', () => {
     });
 
     describe('create', () => {
+        let quiz: QuizDocument;
         let room: sinon.SinonStubbedInstance<Room>;
+        let clientRooms: sinon.SinonStub;
 
         beforeEach(() => {
-            const quiz = { id: 'foo' } as QuizDocument;
+            quiz = { id: 'foo' } as QuizDocument;
             room = sinon.createStubInstance(Room);
-            (room as Writeable<Room>).id = 'bar';
+            (room as Writeable<Room>).game = { id: 'bar' } as Game;
             gameRoomService.create.withArgs(server, quiz, GameType.Normal).returns(room);
 
-            gateway.create(quiz, socket);
+            clientRooms = sinon.stub(socket, 'rooms').value(new Set());
         });
 
-        it('should create a room and join the client', () => {
+        it('should create a room and join the client', async () => {
+            await gateway.create(quiz, socket);
             expect(gameRoomService.create.calledOnce).toBe(true);
             expect(room.addPlayer.calledWith(socket, 'Organisateur')).toBe(true);
         });
 
-        it('should redirect the client to the waiting room', () => {
+        it('should redirect the client to the waiting room', async () => {
+            await gateway.create(quiz, socket);
             expect(socket.emit.calledWith('redirect-to-waiting-room', room.game)).toBe(true);
         });
+
+        it('should leave all previous game rooms', async () => {
+            clientRooms.value(new Set(['foo', 'bar']));
+            gameRoomService.get.withArgs(new Set(['foo'])).returns(room);
+
+            server.in.withArgs('foo').returns({
+                fetchSockets: async () => [],
+            } as unknown as BroadcastOperator<DefaultEventsMap, unknown>);
+
+            await gateway.create(quiz, socket);
+            expect(room.removePlayer.calledOnce).toBe(true);
+        });
     });
 
     describe('demo', () => {
         let room: sinon.SinonStubbedInstance<Room>;
 
-        beforeEach(() => {
+        beforeEach(async () => {
             const quiz = { id: 'foo' } as QuizDocument;
             room = sinon.createStubInstance(Room);
-            (room as Writeable<Room>).id = 'bar';
+            (room as Writeable<Room>).game = { id: 'bar' } as Game;
             gameRoomService.create.withArgs(server, quiz, GameType.Demo).returns(room);
 
-            gateway.demo(quiz, socket);
+            sinon.stub(socket, 'rooms').value(new Set());
+
+            await gateway.demo(quiz, socket);
         });
 
         it('should create a room and join the client', () => {
@@ -116,6 +134,30 @@ describe('GameGateway', () => {
         });
     });
 
+    describe('leave', () => {
+        it('should get the room and remove the player', async () => {
+            const room = sinon.createStubInstance(Room);
+            (room as Writeable<Room>).game = { id: 'foo' } as Game;
+            sinon.stub(socket, 'rooms').value(new Set());
+            gameRoomService.get.withArgs(socket.rooms).returns(room);
+
+            server.in.withArgs('foo').returns({
+                fetchSockets: async () => [],
+            } as unknown as BroadcastOperator<DefaultEventsMap, unknown>);
+
+            await gateway.leave(socket);
+
+            expect(room.removePlayer.calledWith(socket)).toBe(true);
+        });
+
+        it('should throw if the room is not found', async () => {
+            sinon.stub(socket, 'rooms').value(new Set(['foo']));
+            gameRoomService.get.withArgs(socket.rooms).returns(undefined);
+
+            await expect(gateway.leave(socket)).rejects.toThrowError(WsException);
+        });
+    });
+
     describe('handleConnection', () => {
         it('should log the connection', () => {
             (socket as Writeable<Socket>).id = 'foo';
diff --git a/server/app/game/game.gateway.ts b/server/app/game/game.gateway.ts
index 158e40b395cde9839e65d09c671d213fc403fef6..b500a528952c45d03edb47c70159d28c28715e7f 100644
--- a/server/app/game/game.gateway.ts
+++ b/server/app/game/game.gateway.ts
@@ -26,21 +26,15 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect {
     constructor(private gameRoomService: GameRoomService) {}
 
     @SubscribeMessage(GameClientEvent.Create)
-    create(@MessageBody(AvailableQuizPipe) quiz: QuizDocument, @ConnectedSocket() client: Socket) {
-        const room = this.gameRoomService.create(this.server, quiz, GameType.Normal);
-        room.addPlayer(client, GAME_CREATOR_USERNAME);
-
-        this.logger.log(`Game with quiz ${quiz.id} created: ${room.id}`);
+    async create(@MessageBody(AvailableQuizPipe) quiz: QuizDocument, @ConnectedSocket() client: Socket) {
+        const room = await this.createGameRoom(GameType.Normal, quiz, client);
 
         client.emit(GameServerEvent.RedirectToWaitingRoom, room.game, GAME_CREATOR_USERNAME);
     }
 
     @SubscribeMessage(GameClientEvent.Demo)
-    demo(@MessageBody(AvailableQuizPipe) quiz: QuizDocument, @ConnectedSocket() client: Socket) {
-        const room = this.gameRoomService.create(this.server, quiz, GameType.Demo);
-        room.addPlayer(client, GAME_CREATOR_USERNAME);
-
-        this.logger.log(`Demo game with quiz ${quiz.id} created: ${room.id}`);
+    async demo(@MessageBody(AvailableQuizPipe) quiz: QuizDocument, @ConnectedSocket() client: Socket) {
+        const room = await this.createGameRoom(GameType.Demo, quiz, client);
 
         client.emit(GameServerEvent.StartDemo, room.game, GAME_CREATOR_USERNAME);
         room.start();
@@ -56,6 +50,17 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect {
         room.answer(client.id, answers);
     }
 
+    @SubscribeMessage(GameClientEvent.Leave)
+    async leave(@ConnectedSocket() client: Socket) {
+        const room = this.gameRoomService.get(client.rooms);
+        if (!room) {
+            throw new WsException('Room not found');
+        }
+
+        room.removePlayer(client);
+        await this.clearEmptyRooms(new Set([...client.rooms, room.game.id]));
+    }
+
     handleConnection(client: Socket) {
         this.logger.log(`Client connected: ${client.id}`);
 
@@ -71,6 +76,27 @@ export class GameGateway implements OnGatewayConnection, OnGatewayDisconnect {
         this.logger.log(`Client disconnected: ${client.id}`);
     }
 
+    private async createGameRoom(type: GameType, quiz: QuizDocument, client: Socket) {
+        await this.leaveAllGameRooms(client);
+
+        const room = this.gameRoomService.create(this.server, quiz, type);
+        room.addPlayer(client, GAME_CREATOR_USERNAME);
+
+        this.logger.log(`Game with quiz ${quiz.id} created: ${room.game.id}`);
+
+        return room;
+    }
+
+    private async leaveAllGameRooms(client: Socket) {
+        for (const roomId of client.rooms) {
+            const room = this.gameRoomService.get(new Set([roomId]));
+            if (room) {
+                room.removePlayer(client);
+                await this.clearEmptyRooms(new Set([roomId]));
+            }
+        }
+    }
+
     private async clearEmptyRooms(rooms: Set<string>) {
         for (const roomId of rooms) {
             const clients = await this.server.in(roomId).fetchSockets();