diff --git a/packages/backend/src/core/NoteEditService.ts b/packages/backend/src/core/NoteEditService.ts
index dfcff0e5b1..e5918e6c2f 100644
--- a/packages/backend/src/core/NoteEditService.ts
+++ b/packages/backend/src/core/NoteEditService.ts
@@ -14,18 +14,15 @@ import { extractCustomEmojisFromMfm } from '@/misc/extract-custom-emojis-from-mf
 import { extractHashtags } from '@/misc/extract-hashtags.js';
 import type { IMentionedRemoteUsers } from '@/models/Note.js';
 import { MiNote } from '@/models/Note.js';
-import type { NoteEditRepository, ChannelFollowingsRepository, ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, MutingsRepository, NotesRepository, NoteThreadMutingsRepository, UserListMembershipsRepository, UserProfilesRepository, UsersRepository } from '@/models/_.js';
+import type { NoteEditRepository, ChannelFollowingsRepository, ChannelsRepository, FollowingsRepository, InstancesRepository, MiFollowing, MutingsRepository, NotesRepository, NoteThreadMutingsRepository, UserListMembershipsRepository, UserProfilesRepository, UsersRepository, PollsRepository } from '@/models/_.js';
 import type { MiDriveFile } from '@/models/DriveFile.js';
 import type { MiApp } from '@/models/App.js';
 import { concat } from '@/misc/prelude/array.js';
 import { IdService } from '@/core/IdService.js';
 import type { MiUser, MiLocalUser, MiRemoteUser } from '@/models/User.js';
 import { MiPoll, type IPoll } from '@/models/Poll.js';
-import { checkWordMute } from '@/misc/check-word-mute.js';
 import type { MiChannel } from '@/models/Channel.js';
 import { normalizeForSearch } from '@/misc/normalize-for-search.js';
-import { MemorySingleCache } from '@/misc/cache.js';
-import type { MiUserProfile } from '@/models/UserProfile.js';
 import { RelayService } from '@/core/RelayService.js';
 import { FederatedInstanceService } from '@/core/FederatedInstanceService.js';
 import { DI } from '@/di-symbols.js';
@@ -35,7 +32,6 @@ import ActiveUsersChart from '@/core/chart/charts/active-users.js';
 import { GlobalEventService } from '@/core/GlobalEventService.js';
 import { NotificationService } from '@/core/NotificationService.js';
 import { WebhookService } from '@/core/WebhookService.js';
-import { HashtagService } from '@/core/HashtagService.js';
 import { QueueService } from '@/core/QueueService.js';
 import { NoteEntityService } from '@/core/entities/NoteEntityService.js';
 import { UserEntityService } from '@/core/entities/UserEntityService.js';
@@ -48,11 +44,7 @@ import { DB_MAX_NOTE_TEXT_LENGTH } from '@/const.js';
 import { RoleService } from '@/core/RoleService.js';
 import { MetaService } from '@/core/MetaService.js';
 import { SearchService } from '@/core/SearchService.js';
-import { FeaturedService } from '@/core/FeaturedService.js';
 import { FunoutTimelineService } from '@/core/FunoutTimelineService.js';
-import { AntennaService } from './AntennaService.js';
-import NotesChart from './chart/charts/notes.js';
-import PerUserNotesChart from './chart/charts/per-user-notes.js';
 import { UtilityService } from '@/core/UtilityService.js';
 
 type NotificationType = 'reply' | 'renote' | 'quote' | 'mention';
@@ -191,6 +183,9 @@ export class NoteEditService implements OnApplicationShutdown {
 		@Inject(DI.noteEditRepository)
 		private noteEditRepository: NoteEditRepository,
 
+		@Inject(DI.pollsRepository)
+		private pollsRepository: PollsRepository,
+
 		private userEntityService: UserEntityService,
 		private noteEntityService: NoteEntityService,
 		private idService: IdService,
@@ -201,18 +196,13 @@ export class NoteEditService implements OnApplicationShutdown {
 		private notificationService: NotificationService,
 		private relayService: RelayService,
 		private federatedInstanceService: FederatedInstanceService,
-		private hashtagService: HashtagService,
-		private antennaService: AntennaService,
 		private webhookService: WebhookService,
-		private featuredService: FeaturedService,
 		private remoteUserResolveService: RemoteUserResolveService,
 		private apDeliverManagerService: ApDeliverManagerService,
 		private apRendererService: ApRendererService,
 		private roleService: RoleService,
 		private metaService: MetaService,
 		private searchService: SearchService,
-		private notesChart: NotesChart,
-		private perUserNotesChart: PerUserNotesChart,
 		private activeUsersChart: ActiveUsersChart,
 		private instanceChart: InstanceChart,
 		private utilityService: UtilityService,
@@ -385,6 +375,10 @@ export class NoteEditService implements OnApplicationShutdown {
 			update.hasPoll = !!data.poll;
 		}
 
+		const poll = await this.pollsRepository.findOneBy({ noteId: oldnote.id });
+
+		const oldPoll = poll ? { choices: poll.choices, multiple: poll.multiple, expiresAt: poll.expiresAt } : null;
+
 		if (Object.keys(update).length > 0) {
 			const exists = await this.noteEditRepository.findOneBy({ noteId: oldnote.id });
 
@@ -456,7 +450,7 @@ export class NoteEditService implements OnApplicationShutdown {
 				}));
 			}
 
-			if (data.poll != null) {
+			if (data.poll != null && JSON.stringify(data.poll) !== JSON.stringify(oldPoll)) {
 				// Start transaction
 				await this.db.transaction(async transactionalEntityManager => {
 					await transactionalEntityManager.update(MiNote, oldnote.id, note);
diff --git a/packages/backend/src/server/api/endpoints/notes/edit.ts b/packages/backend/src/server/api/endpoints/notes/edit.ts
index 6140c80a5d..49fa4c3bd6 100644
--- a/packages/backend/src/server/api/endpoints/notes/edit.ts
+++ b/packages/backend/src/server/api/endpoints/notes/edit.ts
@@ -14,7 +14,7 @@ import { DI } from '@/di-symbols.js';
 import { ApiError } from '../../error.js';
 
 export const meta = {
-	tags: ["notes"],
+	tags: ['notes'],
 
 	requireCredential: true,
 
@@ -23,99 +23,99 @@ export const meta = {
 		max: 300,
 	},
 
-	kind: "write:notes",
+	kind: 'write:notes',
 
 	res: {
-		type: "object",
+		type: 'object',
 		optional: false,
 		nullable: false,
 		properties: {
 			createdNote: {
-				type: "object",
+				type: 'object',
 				optional: false,
 				nullable: false,
-				ref: "Note",
+				ref: 'Note',
 			},
 		},
 	},
 
 	errors: {
 		noSuchRenoteTarget: {
-			message: "No such renote target.",
-			code: "NO_SUCH_RENOTE_TARGET",
-			id: "b5c90186-4ab0-49c8-9bba-a1f76c282ba4",
+			message: 'No such renote target.',
+			code: 'NO_SUCH_RENOTE_TARGET',
+			id: 'b5c90186-4ab0-49c8-9bba-a1f76c282ba4',
 		},
 
 		cannotReRenote: {
-			message: "You can not Renote a pure Renote.",
-			code: "CANNOT_RENOTE_TO_A_PURE_RENOTE",
-			id: "fd4cc33e-2a37-48dd-99cc-9b806eb2031a",
+			message: 'You can not Renote a pure Renote.',
+			code: 'CANNOT_RENOTE_TO_A_PURE_RENOTE',
+			id: 'fd4cc33e-2a37-48dd-99cc-9b806eb2031a',
 		},
 
 		noSuchReplyTarget: {
-			message: "No such reply target.",
-			code: "NO_SUCH_REPLY_TARGET",
-			id: "749ee0f6-d3da-459a-bf02-282e2da4292c",
+			message: 'No such reply target.',
+			code: 'NO_SUCH_REPLY_TARGET',
+			id: '749ee0f6-d3da-459a-bf02-282e2da4292c',
 		},
 
 		cannotReplyToPureRenote: {
-			message: "You can not reply to a pure Renote.",
-			code: "CANNOT_REPLY_TO_A_PURE_RENOTE",
-			id: "3ac74a84-8fd5-4bb0-870f-01804f82ce15",
+			message: 'You can not reply to a pure Renote.',
+			code: 'CANNOT_REPLY_TO_A_PURE_RENOTE',
+			id: '3ac74a84-8fd5-4bb0-870f-01804f82ce15',
 		},
 
 		cannotCreateAlreadyExpiredPoll: {
-			message: "Poll is already expired.",
-			code: "CANNOT_CREATE_ALREADY_EXPIRED_POLL",
-			id: "04da457d-b083-4055-9082-955525eda5a5",
+			message: 'Poll is already expired.',
+			code: 'CANNOT_CREATE_ALREADY_EXPIRED_POLL',
+			id: '04da457d-b083-4055-9082-955525eda5a5',
 		},
 
 		noSuchChannel: {
-			message: "No such channel.",
-			code: "NO_SUCH_CHANNEL",
-			id: "b1653923-5453-4edc-b786-7c4f39bb0bbb",
+			message: 'No such channel.',
+			code: 'NO_SUCH_CHANNEL',
+			id: 'b1653923-5453-4edc-b786-7c4f39bb0bbb',
 		},
 
 		youHaveBeenBlocked: {
-			message: "You have been blocked by this user.",
-			code: "YOU_HAVE_BEEN_BLOCKED",
-			id: "b390d7e1-8a5e-46ed-b625-06271cafd3d3",
+			message: 'You have been blocked by this user.',
+			code: 'YOU_HAVE_BEEN_BLOCKED',
+			id: 'b390d7e1-8a5e-46ed-b625-06271cafd3d3',
 		},
 
 		accountLocked: {
-			message: "You migrated. Your account is now locked.",
-			code: "ACCOUNT_LOCKED",
-			id: "d390d7e1-8a5e-46ed-b625-06271cafd3d3",
+			message: 'You migrated. Your account is now locked.',
+			code: 'ACCOUNT_LOCKED',
+			id: 'd390d7e1-8a5e-46ed-b625-06271cafd3d3',
 		},
 
 		needsEditId: {
-			message: "You need to specify `editId`.",
-			code: "NEEDS_EDIT_ID",
-			id: "d697edc8-8c73-4de8-bded-35fd198b79e5",
+			message: 'You need to specify `editId`.',
+			code: 'NEEDS_EDIT_ID',
+			id: 'd697edc8-8c73-4de8-bded-35fd198b79e5',
 		},
 
 		noSuchNote: {
-			message: "No such note.",
-			code: "NO_SUCH_NOTE",
-			id: "eef6c173-3010-4a23-8674-7c4fcaeba719",
+			message: 'No such note.',
+			code: 'NO_SUCH_NOTE',
+			id: 'eef6c173-3010-4a23-8674-7c4fcaeba719',
 		},
 
 		youAreNotTheAuthor: {
-			message: "You are not the author of this note.",
-			code: "YOU_ARE_NOT_THE_AUTHOR",
-			id: "c6e61685-411d-43d0-b90a-a448d2539001",
+			message: 'You are not the author of this note.',
+			code: 'YOU_ARE_NOT_THE_AUTHOR',
+			id: 'c6e61685-411d-43d0-b90a-a448d2539001',
 		},
 
 		cannotPrivateRenote: {
-			message: "You can not perform a private renote.",
-			code: "CANNOT_PRIVATE_RENOTE",
-			id: "19a50f1c-84fa-4e33-81d3-17834ccc0ad8",
+			message: 'You can not perform a private renote.',
+			code: 'CANNOT_PRIVATE_RENOTE',
+			id: '19a50f1c-84fa-4e33-81d3-17834ccc0ad8',
 		},
 
 		notLocalUser: {
-			message: "You are not a local user.",
-			code: "NOT_LOCAL_USER",
-			id: "b907f407-2aa0-4283-800b-a2c56290b822",
+			message: 'You are not a local user.',
+			code: 'NOT_LOCAL_USER',
+			id: 'b907f407-2aa0-4283-800b-a2c56290b822',
 		},
 
 		cannotRenoteOutsideOfChannel: {
@@ -127,60 +127,63 @@ export const meta = {
 } as const;
 
 export const paramDef = {
-	type: "object",
+	type: 'object',
 	properties: {
-		editId: { type: "string", format: "misskey:id" },
-		visibility: { type: "string", enum: ['public', 'home', 'followers', 'specified'], default: "public" },
+		editId: { type: 'string', format: 'misskey:id' },
+		visibility: { type: 'string', enum: ['public', 'home', 'followers', 'specified'], default: 'public' },
 		visibleUserIds: {
-			type: "array",
+			type: 'array',
 			uniqueItems: true,
 			items: {
-				type: "string",
-				format: "misskey:id",
+				type: 'string',
+				format: 'misskey:id',
 			},
 		},
-		text: { type: "string", maxLength: MAX_NOTE_TEXT_LENGTH, nullable: true },
-		cw: { type: "string", nullable: true, minLength: 1, maxLength: 250 },
-		localOnly: { type: "boolean", default: false },
-		noExtractMentions: { type: "boolean", default: false },
-		noExtractHashtags: { type: "boolean", default: false },
-		noExtractEmojis: { type: "boolean", default: false },
+		cw: { type: 'string', nullable: true, minLength: 1, maxLength: 250 },
+		localOnly: { type: 'boolean', default: false },
+		reactionAcceptance: { type: 'string', nullable: true, enum: [null, 'likeOnly', 'likeOnlyForRemote', 'nonSensitiveOnly', 'nonSensitiveOnlyForLocalLikeOnlyForRemote'], default: null },
+		noExtractMentions: { type: 'boolean', default: false },
+		noExtractHashtags: { type: 'boolean', default: false },
+		noExtractEmojis: { type: 'boolean', default: false },
+		replyId: { type: 'string', format: 'misskey:id', nullable: true },
+		renoteId: { type: 'string', format: 'misskey:id', nullable: true },
+		channelId: { type: 'string', format: 'misskey:id', nullable: true },
+		text: {
+			type: 'string',
+			minLength: 1,
+			maxLength: MAX_NOTE_TEXT_LENGTH,
+			nullable: true,
+		},
 		fileIds: {
-			type: "array",
+			type: 'array',
 			uniqueItems: true,
 			minItems: 1,
 			maxItems: 16,
-			items: { type: "string", format: "misskey:id" },
+			items: { type: 'string', format: 'misskey:id' },
 		},
 		mediaIds: {
-			deprecated: true,
-			description:
-				"Use `fileIds` instead. If both are specified, this property is discarded.",
-			type: "array",
+			type: 'array',
 			uniqueItems: true,
 			minItems: 1,
 			maxItems: 16,
-			items: { type: "string", format: "misskey:id" },
+			items: { type: 'string', format: 'misskey:id' },
 		},
-		replyId: { type: "string", format: "misskey:id", nullable: true },
-		renoteId: { type: "string", format: "misskey:id", nullable: true },
-		channelId: { type: "string", format: "misskey:id", nullable: true },
 		poll: {
-			type: "object",
+			type: 'object',
 			nullable: true,
 			properties: {
 				choices: {
-					type: "array",
+					type: 'array',
 					uniqueItems: true,
 					minItems: 2,
 					maxItems: 10,
-					items: { type: "string", minLength: 1, maxLength: 50 },
+					items: { type: 'string', minLength: 1, maxLength: 50 },
 				},
-				multiple: { type: "boolean", default: false },
-				expiresAt: { type: "integer", nullable: true },
-				expiredAfter: { type: "integer", nullable: true, minimum: 1 },
+				multiple: { type: 'boolean' },
+				expiresAt: { type: 'integer', nullable: true },
+				expiredAfter: { type: 'integer', nullable: true, minimum: 1 },
 			},
-			required: ["choices"],
+			required: ['choices'],
 		},
 	},
 	anyOf: [
@@ -188,32 +191,32 @@ export const paramDef = {
 			// (re)note with text, files and poll are optional
 			properties: {
 				text: {
-					type: "string",
+					type: 'string',
 					minLength: 1,
 					maxLength: MAX_NOTE_TEXT_LENGTH,
 					nullable: false,
 				},
 			},
-			required: ["text"],
+			required: ['text'],
 		},
 		{
 			// (re)note with files, text and poll are optional
-			required: ["fileIds"],
+			required: ['fileIds'],
 		},
 		{
 			// (re)note with files, text and poll are optional
-			required: ["mediaIds"],
+			required: ['mediaIds'],
 		},
 		{
 			// (re)note with poll, text and files are optional
 			properties: {
-				poll: { type: "object", nullable: false },
+				poll: { type: 'object', nullable: false },
 			},
-			required: ["poll"],
+			required: ['poll'],
 		},
 		{
 			// pure renote
-			required: ["renoteId"],
+			required: ['renoteId'],
 		},
 	],
 } as const;
diff --git a/packages/frontend/src/components/MkPostForm.vue b/packages/frontend/src/components/MkPostForm.vue
index f72e4ddfc3..74038cd62c 100644
--- a/packages/frontend/src/components/MkPostForm.vue
+++ b/packages/frontend/src/components/MkPostForm.vue
@@ -931,8 +931,8 @@ onMounted(() => {
 				poll = {
 					choices: init.poll.choices.map(x => x.text),
 					multiple: init.poll.multiple,
-					expiresAt: init.poll.expiresAt,
-					expiredAfter: init.poll.expiredAfter,
+					expiresAt: init.poll.expiresAt ? new Date(init.poll.expiresAt).getTime().toString() : null,
+					expiredAfter: init.poll.expiredAfter ? new Date(init.poll.expiredAfter).getTime().toString() : null,
 				};
 			}
 			visibility = init.visibility;
diff --git a/packages/misskey-js/src/entities.ts b/packages/misskey-js/src/entities.ts
index ec9a3d45c3..10b9dd5eb4 100644
--- a/packages/misskey-js/src/entities.ts
+++ b/packages/misskey-js/src/entities.ts
@@ -217,6 +217,7 @@ export type Note = {
 	clippedCount?: number;
 	poll?: {
 		expiresAt: DateString | null;
+		expiredAfter: DateString | null;
 		multiple: boolean;
 		choices: {
 			isVoted: boolean;