diff --git a/packages/backend/src/server/api/error.ts b/packages/backend/src/server/api/error.ts
index 176144f3e..201c234b7 100644
--- a/packages/backend/src/server/api/error.ts
+++ b/packages/backend/src/server/api/error.ts
@@ -36,7 +36,7 @@ export class ApiError extends Error {
 				break;
 			case 429:
 				if (typeof this.info === 'object' && typeof this.info.reset === 'number') {
-					ctx.respose.set('Retry-After', Math.floor(this.info.reset - (Date.now() / 1000)));
+					ctx.response.set('Retry-After', Math.floor(this.info.reset - (Date.now() / 1000)));
 				}
 				break;
 		}
diff --git a/packages/backend/src/server/api/limiter.ts b/packages/backend/src/server/api/limiter.ts
index 2780afff3..63aba87bf 100644
--- a/packages/backend/src/server/api/limiter.ts
+++ b/packages/backend/src/server/api/limiter.ts
@@ -6,7 +6,7 @@ import { ApiError } from './error.js';
 
 const logger = new Logger('limiter');
 
-export const limiter = (limitation: IEndpointMeta['limit'] & { key: NonNullable<string> }, actor: string) => new Promise<void>((resolve) => {
+export const limiter = (limitation: IEndpointMeta['limit'] & { key: NonNullable<string> }, actor: string) => new Promise<void>((resolve, reject) => {
 	if (process.env.NODE_ENV === 'test') resolve();
 
 	const hasShortTermLimit = typeof limitation.minInterval === 'number';
@@ -15,45 +15,8 @@ export const limiter = (limitation: IEndpointMeta['limit'] & { key: NonNullable<
 		typeof limitation.duration === 'number' &&
 		typeof limitation.max === 'number';
 
-	if (hasShortTermLimit) {
-		min();
-	} else if (hasLongTermLimit) {
-		max();
-	} else {
-		resolve();
-	}
-
-	// Short-term limit, calls long term limit if appropriate.
-	function min(): void {
-		const minIntervalLimiter = new Limiter({
-			id: `${actor}:${limitation.key}:min`,
-			duration: limitation.minInterval,
-			max: 1,
-			db: redisClient,
-		});
-
-		minIntervalLimiter.get((err, info) => {
-			if (err) {
-				logger.error(err);
-				throw new ApiError('INTERNAL_ERROR');
-			}
-
-			logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);
-
-			if (info.remaining === 0) {
-				throw new ApiError('RATE_LIMIT_EXCEEDED', info);
-			} else {
-				if (hasLongTermLimit) {
-					max();
-				} else {
-					resolve();
-				}
-			}
-		});
-	}
-
 	// Long term limit
-	function max(): void {
+	const max = (): void => {
 		const limiter = new Limiter({
 			id: `${actor}:${limitation.key}`,
 			duration: limitation.duration,
@@ -64,16 +27,53 @@ export const limiter = (limitation: IEndpointMeta['limit'] & { key: NonNullable<
 		limiter.get((err, info) => {
 			if (err) {
 				logger.error(err);
-				throw new ApiError('INTERNAL_ERROR');
+				reject(new ApiError('INTERNAL_ERROR'));
 			}
 
 			logger.debug(`${actor} ${limitation.key} max remaining: ${info.remaining}`);
 
 			if (info.remaining === 0) {
-				throw new ApiError('RATE_LIMIT_EXCEEDED', info);
+				reject(new ApiError('RATE_LIMIT_EXCEEDED', info));
 			} else {
 				resolve();
 			}
 		});
 	}
+
+	// Short-term limit, calls long term limit if appropriate.
+	const min = (): void => {
+		const minIntervalLimiter = new Limiter({
+			id: `${actor}:${limitation.key}:min`,
+			duration: limitation.minInterval,
+			max: 1,
+			db: redisClient,
+		});
+
+		minIntervalLimiter.get((err, info) => {
+			if (err) {
+				logger.error(err);
+				reject(new ApiError('INTERNAL_ERROR'));
+			}
+
+			logger.debug(`${actor} ${limitation.key} min remaining: ${info.remaining}`);
+
+			if (info.remaining === 0) {
+				reject(new ApiError('RATE_LIMIT_EXCEEDED', info));
+			} else {
+				if (hasLongTermLimit) {
+					max();
+				} else {
+					resolve();
+				}
+			}
+		});
+	}
+
+	if (hasShortTermLimit) {
+		min();
+	} else if (hasLongTermLimit) {
+		max();
+	} else {
+		resolve();
+	}
 });