diff --git a/packages/backend/src/misc/cache.ts b/packages/backend/src/misc/cache.ts
index 76835b44b13f11616d9bb84446659f099d5ab152..e9966b77859786391348f930997985eb29d20ba9 100644
--- a/packages/backend/src/misc/cache.ts
+++ b/packages/backend/src/misc/cache.ts
@@ -28,11 +28,22 @@ export class Cache<T> {
 		this.cache.delete(key);
 	}
 
-	public async fetch(key: string | null, fetcher: () => Promise<T>): Promise<T> {
+	/**
+	 * キャッシュがあればそれを返し、無ければfetcherを呼び出して結果をキャッシュ&返します
+	 * optional: キャッシュが存在してもvalidatorでfalseを返すとキャッシュ無効扱いにします
+	 */
+	public async fetch(key: string | null, fetcher: () => Promise<T>, validator?: (cachedValue: T) => boolean): Promise<T> {
 		const cachedValue = this.get(key);
 		if (cachedValue !== undefined) {
-			// Cache HIT
-			return cachedValue;
+			if (validator) {
+				if (validator(cachedValue)) {
+					// Cache HIT
+					return cachedValue;
+				}
+			} else {
+				// Cache HIT
+				return cachedValue;
+			}
 		}
 
 		// Cache MISS
diff --git a/packages/backend/src/models/repositories/user.ts b/packages/backend/src/models/repositories/user.ts
index a909ab3ba682dcb43c7b911c37246f97183b41d4..17b7987a4ead2ff3d09f8f4deae3e371455c2551 100644
--- a/packages/backend/src/models/repositories/user.ts
+++ b/packages/backend/src/models/repositories/user.ts
@@ -8,6 +8,10 @@ import { awaitAll, Promiseable } from '@/prelude/await-all.js';
 import { populateEmojis } from '@/misc/populate-emojis.js';
 import { getAntennas } from '@/misc/antenna-cache.js';
 import { USER_ACTIVE_THRESHOLD, USER_ONLINE_THRESHOLD } from '@/const.js';
+import { Cache } from '@/misc/cache.js';
+import { Instance } from '../entities/instance.js';
+
+const userInstanceCache = new Cache<Instance | null>(1000 * 60 * 60 * 3);
 
 type IsUserDetailed<Detailed extends boolean> = Detailed extends true ? Packed<'UserDetailed'> : Packed<'UserLite'>;
 type IsMeAndIsUserDetailed<ExpectsMe extends boolean | null, Detailed extends boolean> =
@@ -254,8 +258,11 @@ export class UserRepository extends Repository<User> {
 			isModerator: user.isModerator || falsy,
 			isBot: user.isBot || falsy,
 			isCat: user.isCat || falsy,
-			showTimelineReplies: user.showTimelineReplies || falsy,
-			instance: user.host ? Instances.findOne({ host: user.host }).then(instance => instance ? {
+			// TODO: typeorm 3.0にしたら .then(x => x || null) は消せる
+			instance: user.host ? userInstanceCache.fetch(user.host,
+				() => Instances.findOne({ host: user.host }).then(x => x || null),
+				v => v != null
+			).then(instance => instance ? {
 				name: instance.name,
 				softwareName: instance.softwareName,
 				softwareVersion: instance.softwareVersion,
@@ -334,6 +341,7 @@ export class UserRepository extends Repository<User> {
 				mutedInstances: profile!.mutedInstances,
 				mutingNotificationTypes: profile!.mutingNotificationTypes,
 				emailNotificationTypes: profile!.emailNotificationTypes,
+				showTimelineReplies: user.showTimelineReplies || falsy,
 			} : {}),
 
 			...(opts.includeSecrets ? {