diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000000..614d50d0ff
--- /dev/null
+++ b/CHANGELOG.md
@@ -0,0 +1,11 @@
+ChangeLog
+=========
+
+3.0.0
+-----
+
+### Migration
+
+起動する前に、`node cli/recount-stats`してください。
+
+Please run `node cli/recount-stats` before launch.
diff --git a/cli/recount-stats.js b/cli/recount-stats.js
new file mode 100644
index 0000000000..84cb5d0f57
--- /dev/null
+++ b/cli/recount-stats.js
@@ -0,0 +1,42 @@
+const { default: Note } = require('../built/models/note');
+const { default: Meta } = require('../built/models/meta');
+const { default: User } = require('../built/models/user');
+
+async function main() {
+	const meta = await Meta.findOne({});
+
+	const notesCount = await Note.count();
+
+	const usersCount = await User.count();
+
+	const originalNotesCount = await Note.count({
+		'_user.host': null
+	});
+
+	const originalUsersCount = await User.count({
+		host: null
+	});
+
+	const stats = {
+		notesCount,
+		usersCount,
+		originalNotesCount,
+		originalUsersCount
+	};
+
+	if (meta) {
+		await Meta.update({}, {
+			$set: {
+				stats
+			}
+		});
+	} else {
+		await Meta.insert({
+			stats
+		});
+	}
+}
+
+main().then(() => {
+	console.log('done');
+}).catch(console.error);
diff --git a/package.json b/package.json
index 6aea76fc37..72cbc7356b 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
 {
 	"name": "misskey",
 	"author": "syuilo <i@syuilo.com>",
-	"version": "2.42.0",
+	"version": "3.0.0",
 	"clientVersion": "1.0.6517",
 	"codename": "nighthike",
 	"main": "./built/index.js",
diff --git a/src/models/meta.ts b/src/models/meta.ts
index 710bb23382..11b9b186ce 100644
--- a/src/models/meta.ts
+++ b/src/models/meta.ts
@@ -5,4 +5,10 @@ export default Meta;
 
 export type IMeta = {
 	broadcasts: any[];
+	stats: {
+		notesCount: number;
+		originalNotesCount: number;
+		usersCount: number;
+		originalUsersCount: number;
+	};
 };
diff --git a/src/remote/activitypub/models/person.ts b/src/remote/activitypub/models/person.ts
index 96e73406b2..42ee5a27df 100644
--- a/src/remote/activitypub/models/person.ts
+++ b/src/remote/activitypub/models/person.ts
@@ -10,6 +10,7 @@ import Resolver from '../resolver';
 import { resolveImage } from './image';
 import { isCollectionOrOrderedCollection, IObject, IPerson } from '../type';
 import { IDriveFile } from '../../../models/drive-file';
+import Meta from '../../../models/meta';
 
 const log = debug('misskey:activitypub');
 
@@ -117,6 +118,14 @@ export async function createPerson(value: any, resolver?: Resolver): Promise<IUs
 		throw e;
 	}
 
+	//#region Increment users count
+	Meta.update({}, {
+		$inc: {
+			'stats.usersCount': 1
+		}
+	}, { upsert: true });
+	//#endregion
+
 	//#region アイコンとヘッダー画像をフェッチ
 	const [avatar, banner] = (await Promise.all<IDriveFile>([
 		person.icon,
diff --git a/src/server/api/endpoints/stats.ts b/src/server/api/endpoints/stats.ts
index d1e17651f2..74ab6ba945 100644
--- a/src/server/api/endpoints/stats.ts
+++ b/src/server/api/endpoints/stats.ts
@@ -1,26 +1,10 @@
-import Note from '../../../models/note';
-import User from '../../../models/user';
+import Meta from '../../../models/meta';
 
 /**
  * Get the misskey's statistics
  */
-module.exports = params => new Promise(async (res, rej) => {
-	const notesCount = await Note.count();
+module.exports = () => new Promise(async (res, rej) => {
+	const meta = await Meta.findOne();
 
-	const usersCount = await User.count();
-
-	const originalNotesCount = await Note.count({
-		'_user.host': null
-	});
-
-	const originalUsersCount = await User.count({
-		host: null
-	});
-
-	res({
-		notesCount,
-		usersCount,
-		originalNotesCount,
-		originalUsersCount
-	});
+	res(meta.stats);
 });
diff --git a/src/server/api/private/signup.ts b/src/server/api/private/signup.ts
index 14d4b8a3fc..fee899b374 100644
--- a/src/server/api/private/signup.ts
+++ b/src/server/api/private/signup.ts
@@ -5,6 +5,7 @@ import recaptcha = require('recaptcha-promise');
 import User, { IUser, validateUsername, validatePassword, pack } from '../../../models/user';
 import generateUserToken from '../common/generate-native-user-token';
 import config from '../../../config';
+import Meta from '../../../models/meta';
 
 recaptcha.init({
 	secret_key: config.recaptcha.secret_key
@@ -93,6 +94,15 @@ export default async (ctx: Koa.Context) => {
 		}
 	});
 
+	//#region Increment users count
+	Meta.update({}, {
+		$inc: {
+			'stats.usersCount': 1,
+			'stats.originalUsersCount': 1
+		}
+	}, { upsert: true });
+	//#endregion
+
 	// Response
 	ctx.body = await pack(account);
 };
diff --git a/src/services/note/create.ts b/src/services/note/create.ts
index f74d04ae62..b21bfa316e 100644
--- a/src/services/note/create.ts
+++ b/src/services/note/create.ts
@@ -18,6 +18,7 @@ import parse from '../../text/parse';
 import { IApp } from '../../models/app';
 import UserList from '../../models/user-list';
 import resolveUser from '../../remote/resolve-user';
+import Meta from '../../models/meta';
 
 type Reason = 'reply' | 'quote' | 'mention';
 
@@ -167,7 +168,24 @@ export default async (user: IUser, data: {
 
 	res(note);
 
-	// Increment notes count
+	//#region Increment notes count
+	if (isLocalUser(user)) {
+		Meta.update({}, {
+			$inc: {
+				'stats.notesCount': 1,
+				'stats.originalNotesCount': 1
+			}
+		}, { upsert: true });
+	} else {
+		Meta.update({}, {
+			$inc: {
+				'stats.notesCount': 1
+			}
+		}, { upsert: true });
+	}
+	//#endregion
+
+	// Increment notes count (user)
 	User.update({ _id: user._id }, {
 		$inc: {
 			notesCount: 1