Compare commits

...
Author SHA1 Message Date
Sonarly Claude Code 0c9186e731 fix: add missing index on workspace.subdomain to prevent auth timeouts
https://sonarly.com/issue/35881?type=bug

Users attempting to login via password credentials experience 10-second timeouts because the workspace lookup by subdomain lacks a database index, causing full table scans that fail under database load.

Fix: Added a database index on the `workspace.subdomain` column to fix 10-second query timeouts during authentication.

**Changes:**

1. **workspace.entity.ts** - Added `@Index('IDX_WORKSPACE_SUBDOMAIN')` decorator to the subdomain field, following the same pattern used for `activationStatus` (which has `@Index('IDX_WORKSPACE_ACTIVATION_STATUS')`).

2. **2-4-instance-command-fast-1778200000000-add-workspace-subdomain-index.ts** - Created a new FastInstanceCommand that runs during the 2.4.0 upgrade to create the index using `CREATE INDEX CONCURRENTLY IF NOT EXISTS`. The CONCURRENTLY option ensures the index is built without locking the table, preventing production impact.

3. **instance-commands.constant.ts** - Registered the new instance command.

**Why this works:**
- The `getWorkspaceByOriginOrDefaultWorkspace()` function queries workspace by subdomain on every authentication request (login, email verification, OTP, OAuth)
- Without an index, PostgreSQL must scan the entire workspace table
- Under load, this caused 10+ second query times that exceeded the timeout
- The new index allows O(log n) lookups instead of O(n) table scans

**Immediate mitigation for production:**
The index can be added manually to the production database before deploying this code:
```sql
CREATE INDEX CONCURRENTLY IF NOT EXISTS "IDX_WORKSPACE_SUBDOMAIN" ON "core"."workspace" ("subdomain");
```
This is safe to run while the application is serving traffic.
2026-05-07 18:04:56 +00:00
3 changed files with 24 additions and 0 deletions
@@ -0,0 +1,21 @@
import { QueryRunner } from 'typeorm';
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
@RegisteredInstanceCommand('2.4.0', 1778200000000)
export class AddWorkspaceSubdomainIndexFastInstanceCommand
implements FastInstanceCommand
{
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'CREATE INDEX CONCURRENTLY IF NOT EXISTS "IDX_WORKSPACE_SUBDOMAIN" ON "core"."workspace" ("subdomain")',
);
}
public async down(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(
'DROP INDEX CONCURRENTLY IF EXISTS "core"."IDX_WORKSPACE_SUBDOMAIN"',
);
}
}
@@ -19,6 +19,7 @@ import { AddIsPreInstalledToApplicationRegistrationFastInstanceCommand } from 's
import { AddProviderExecutedToAgentMessagePartFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-1/2-1-instance-command-fast-1777012800000-add-provider-executed-to-agent-message-part';
import { BackfillPageLayoutWidgetPositionSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/2-1/2-1-instance-command-slow-1795000002000-backfill-page-layout-widget-position';
import { AddMetadataToBillingPriceFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-4/2-4-instance-command-fast-1777100000000-add-metadata-to-billing-price';
import { AddWorkspaceSubdomainIndexFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-4/2-4-instance-command-fast-1778200000000-add-workspace-subdomain-index';
import { AddCacheTokensToAgentChatThreadFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-2/2-2-instance-command-fast-1777455269302-add-cache-tokens-to-agent-chat-thread';
import { AddLogoToApplicationFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-2/2-2-instance-command-fast-1777539664664-add-logo-to-application';
import { AddUpgradeMigrationWorkspaceIdIndexFastInstanceCommand } from 'src/database/commands/upgrade-version-command/2-3/2-3-instance-command-fast-1777308014234-add-upgrade-migration-workspace-id-index';
@@ -51,6 +52,7 @@ export const INSTANCE_COMMANDS = [
AddProviderExecutedToAgentMessagePartFastInstanceCommand,
BackfillPageLayoutWidgetPositionSlowInstanceCommand,
AddMetadataToBillingPriceFastInstanceCommand,
AddWorkspaceSubdomainIndexFastInstanceCommand,
AddCacheTokensToAgentChatThreadFastInstanceCommand,
AddLogoToApplicationFastInstanceCommand,
AddDeletedAtToAgentChatThreadFastInstanceCommand,
@@ -240,6 +240,7 @@ export class WorkspaceEntity {
@Field()
@Column({ unique: true })
@Index('IDX_WORKSPACE_SUBDOMAIN')
subdomain: string;
@Field(() => String, { nullable: true })