diff --git a/packages/backend/src/core/ReversiService.ts b/packages/backend/src/core/ReversiService.ts
index 1d2c168f59d635e61164a09126db14e4c28b0cff..f74416a58a8e95dc656a61fbf97e793937b5c26f 100644
--- a/packages/backend/src/core/ReversiService.ts
+++ b/packages/backend/src/core/ReversiService.ts
@@ -24,7 +24,7 @@ import { Serialized } from '@/types.js';
 import { ReversiGameEntityService } from './entities/ReversiGameEntityService.js';
 import type { OnApplicationShutdown, OnModuleInit } from '@nestjs/common';
 
-const MATCHING_TIMEOUT_MS = 1000 * 20; // 20sec
+const INVITATION_TIMEOUT_MS = 1000 * 20; // 20sec
 
 @Injectable()
 export class ReversiService implements OnApplicationShutdown, OnModuleInit {
@@ -112,7 +112,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 		//#region 相手から既に招待されてないか確認
 		const invitations = await this.redisClient.zrange(
 			`reversi:matchSpecific:${me.id}`,
-			Date.now() - MATCHING_TIMEOUT_MS,
+			Date.now() - INVITATION_TIMEOUT_MS,
 			'+inf',
 			'BYSCORE');
 
@@ -157,7 +157,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 		//#region まず自分宛ての招待を探す
 		const invitations = await this.redisClient.zrange(
 			`reversi:matchSpecific:${me.id}`,
-			Date.now() - MATCHING_TIMEOUT_MS,
+			Date.now() - INVITATION_TIMEOUT_MS,
 			'+inf',
 			'BYSCORE');
 
@@ -173,15 +173,14 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 
 		const matchings = await this.redisClient.zrange(
 			'reversi:matchAny',
-			Date.now() - MATCHING_TIMEOUT_MS,
-			'+inf',
-			'BYSCORE');
+			0,
+			2, // 自分自身のIDが入っている場合もあるので2つ取得
+			'REV');
 
 		const userIds = matchings.filter(id => id !== me.id);
 
 		if (userIds.length > 0) {
-			// pick random
-			const matchedUserId = userIds[Math.floor(Math.random() * userIds.length)];
+			const matchedUserId = userIds[0];
 
 			await this.redisClient.zrem('reversi:matchAny', me.id, matchedUserId);
 
@@ -191,7 +190,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 		} else {
 			const redisPipeline = this.redisClient.pipeline();
 			redisPipeline.zadd('reversi:matchAny', Date.now(), me.id);
-			redisPipeline.expire('reversi:matchAny', 120, 'NX');
+			redisPipeline.expire('reversi:matchAny', 15, 'NX');
 			await redisPipeline.exec();
 			return null;
 		}
@@ -380,7 +379,7 @@ export class ReversiService implements OnApplicationShutdown, OnModuleInit {
 	public async getInvitations(user: MiUser): Promise<MiUser['id'][]> {
 		const invitations = await this.redisClient.zrange(
 			`reversi:matchSpecific:${user.id}`,
-			Date.now() - MATCHING_TIMEOUT_MS,
+			Date.now() - INVITATION_TIMEOUT_MS,
 			'+inf',
 			'BYSCORE');
 		return invitations;
diff --git a/packages/frontend/src/pages/reversi/index.vue b/packages/frontend/src/pages/reversi/index.vue
index 1aa68ae871446acd313294a2af34400850f0cc65..7c687e813c10860bb30999120d1a3c18d97a1fdb 100644
--- a/packages/frontend/src/pages/reversi/index.vue
+++ b/packages/frontend/src/pages/reversi/index.vue
@@ -230,6 +230,8 @@ onMounted(() => {
 	misskeyApi('reversi/invitations').then(_invitations => {
 		invitations.value = _invitations;
 	});
+
+	window.addEventListener('beforeunload', cancelMatching);
 });
 
 onDeactivated(() => {