[PM-27605] Populate MaxStorageGbIncreased for storage increase from 1GB to 5GB.#6579
Conversation
This migration populates the MaxStorageGbIncreased column for Users and Organizations by setting it to MaxStorageGb + 4, representing the storage increase from 1GB to 5GB. This migration depends on PM-27603 being deployed first to create the MaxStorageGbIncreased column. Target release: January 6th, 2026 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
|
Claude finished @cyprain-okeke's task in 1m 52s —— View job Code Review CompleteI've reviewed this PR and identified several issues that should be addressed before merging. Critical Issues1. Missing Transaction Control The migration script While the idempotency check ( Recommendation: Wrap the entire migration in proper transaction blocks with error handling, though this is complicated by the 2. GO Statements Break Transaction Scope The migration file contains multiple Impact: If the Organization table update succeeds but the User table update fails, you'll have inconsistent data with no automatic rollback. Recommendation: Remove unnecessary 3. Index Creation Without ONLINE Option The temporary indexes are created without the Recommendation: CREATE INDEX IX_TEMP_User_MaxStorageGb_MaxStorageGbIncreased
ON [User]([MaxStorageGb], [MaxStorageGbIncreased])
WITH (ONLINE = ON);Note: This requires Enterprise Edition. Consider adding conditional logic or documenting the requirement. Important Issues4. Batch Delay May Be Insufficient The 100ms delay between batches (lines 63, 112) may not provide sufficient throttling for Azure SQL Database with DTU limits. With 5000-record batches, this could trigger throttling or DTU exhaustion. Recommendation: Increase delay to 250-500ms or implement dynamic throttling based on 5. Missing Progress Timestamps The migration includes progress logging but no timestamps. With 183,000 records, the migration could take 6-7 minutes minimum. DBAs cannot estimate completion time or identify if the migration is stalled. Recommendation: Add timestamp logging: PRINT CONCAT('Batch completed at: ', GETDATE(), ' - Total: ', @TotalUpdated);Positive Aspects
NotesThe logic difference between migration and stored procedures is correct and intentional per the PR discussion:
This requires coordinated deployment with the pricing service updates. |
| @@ -0,0 +1,13 @@ | |||
| -- Populate MaxStorageGbIncreased for Users | |||
There was a problem hiding this comment.
❌ Missing column existence check
This migration will fail with a cryptic error if the MaxStorageGbIncreased column doesn't exist (PM-27603 not deployed).
Recommendation: Add a check at the start of the migration:
-- Verify MaxStorageGbIncreased column exists before proceeding
IF NOT EXISTS (
SELECT * FROM sys.columns
WHERE object_id = OBJECT_ID('[dbo].[User]')
AND name = 'MaxStorageGbIncreased'
)
BEGIN
RAISERROR('MaxStorageGbIncreased column does not exist in User table. PM-27603 must be deployed first.', 16, 1);
RETURN;
END;
IF NOT EXISTS (
SELECT * FROM sys.columns
WHERE object_id = OBJECT_ID('[dbo].[Organization]')
AND name = 'MaxStorageGbIncreased'
)
BEGIN
RAISERROR('MaxStorageGbIncreased column does not exist in Organization table. PM-27603 must be deployed first.', 16, 1);
RETURN;
END;
GOThis provides a clear deployment dependency error rather than "invalid column name" errors.
| UPDATE [dbo].[User] | ||
| SET [MaxStorageGbIncreased] = [MaxStorageGb] + 4 | ||
| WHERE [MaxStorageGb] IS NOT NULL; | ||
| GO |
There was a problem hiding this comment.
💭 Transaction safety consideration
The GO statement here commits the User table update as a separate transaction from the Organization update. This means:
- ✅ Pro: Reduces lock duration, better for production with 148k User records
⚠️ Con: If Organization update fails, User table will have been updated but Organization table won't (partial completion)
Question: Is this intentional to minimize lock contention, or should both updates be wrapped in a single transaction for atomicity?
If atomicity is needed:
BEGIN TRANSACTION;
-- User update
-- Organization update
COMMIT TRANSACTION;
GOPlease clarify the intended behavior for this migration.
|
New Issues (1)Checkmarx found the following issues in this Pull Request
|
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #6579 +/- ##
==========================================
+ Coverage 54.60% 58.41% +3.80%
==========================================
Files 1921 1921
Lines 85474 85474
Branches 7648 7648
==========================================
+ Hits 46677 49933 +3256
+ Misses 37020 33690 -3330
- Partials 1777 1851 +74 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
mkincaid-bw
left a comment
There was a problem hiding this comment.
How is the logic going to correlate with the actual enablement of the additional 4GB? From what I can tell, once this PR deploys, then any new Users/Orgs that get created, or Users/Orgs that get updated, will have the MaxStorageGbIncreased set to the same as MaxStorageGb. Is that logic correct? It seems like if we deploy this PR but don't enable the actual increase until later, then new Users/Orgs will get set to the old default, and then won't get updated since the migration will have already run. Am I missing something?
|
|
||
| WHILE @RowsAffected > 0 | ||
| BEGIN | ||
| UPDATE TOP (@BatchSize) [dbo].[User] |
There was a problem hiding this comment.
This migration is going to take quite a while. There's no index on the MaxStorageGb column so the script as-is will force hundreds (or thousands) of table scans - one for each update statement in the batch.
I tested this alternative against a backup (creating an index first) and it ran in 3-4 minutes:
IF NOT EXISTS (
SELECT 1
FROM sys.indexes
WHERE object_id = OBJECT_ID('dbo.User')
AND name = 'IX_TEMP_User_MaxStorageGb_MaxStorageGbIncreased'
)
BEGIN
CREATE INDEX IX_TEMP_User_MaxStorageGb_MaxStorageGbIncreased
ON [User]([MaxStorageGb], [MaxStorageGbIncreased]);
END
GO
DECLARE @BatchSize INT = 5000;
DECLARE @RowsAffected INT = 1;
DECLARE @TotalUpdated INT = 0;
PRINT 'Starting User table update...';
WHILE @RowsAffected > 0
BEGIN
UPDATE TOP (@BatchSize) [dbo].[User]
SET [MaxStorageGbIncreased] = [MaxStorageGb] + 4
WHERE [MaxStorageGb] IS NOT NULL
AND [MaxStorageGbIncreased] IS NULL; -- Only update rows not yet processed
SET @RowsAffected = @@ROWCOUNT;
SET @TotalUpdated = @TotalUpdated + @RowsAffected;
PRINT 'Users updated: ' + CAST(@TotalUpdated AS VARCHAR(10));
WAITFOR DELAY '00:00:00.100'; -- 100ms delay to reduce contention
END
PRINT 'User table update complete. Total rows updated: ' + CAST(@TotalUpdated AS VARCHAR(10));
GO
DROP INDEX IF EXISTS [dbo].[User].[IX_TEMP_User_MaxStorageGb_MaxStorageGbIncreased];
GOThere was a problem hiding this comment.
The logic works correctly when both changes deploy together or in the correct sequence:
- This migration script (2025-11-14_00_PopulateMaxStorageGbIncreased.sql):
- Runs once during deployment
- Updates existing records: MaxStorageGbIncreased = MaxStorageGb + 4
- Migrates old 1GB quota → new 5GB quota - Stored procedures (e.g., User_Create, Organization_Create,User_Update,Organization_Update):
- For new records created after this PR
- Set MaxStorageGbIncreased = @MaxStorageGb (same value, not +4)
- The @MaxStorageGb parameter comes from the API/Pricing Service - Pricing Service (separate deployment):
- Updates plan definitions: 1GB → 5GB
- API calls stored procedures with @MaxStorageGb = 5
|
@cyprain-okeke This looks good - however, it has to be merged for a specific release so leave the |
mkincaid-bw
left a comment
There was a problem hiding this comment.
Discussed this with Conner. In Isolation, the PR is approved, but changes will need to be coordinated with @cd-bitwarden on PR 6482 to ensure changes are not overwritten.



🎟️ Tracking
https://bitwarden.atlassian.net/browse/PM-27605
📔 Objective
This PR implements the transition migration for PM-27605: Populate MaxStorageGbIncreased for storage increase from 1GB to 5GB.
This migration populates the MaxStorageGbIncreased column (added in PM-27603) by setting it to MaxStorageGb + 4 for all User and Organization records that have a storage quota defined.
Changes
Dependencies
Database Impact
According to the ticket, as of October 28th, 2025:
📸 Screenshots
⏰ Reminders before review
🦮 Reviewer guidelines
:+1:) or similar for great changes:memo:) or ℹ️ (:information_source:) for notes or general info:question:) for questions:thinking:) or 💭 (:thought_balloon:) for more open inquiry that's not quite a confirmed issue and could potentially benefit from discussion:art:) for suggestions / improvements:x:) or:warning:) for more significant problems or concerns needing attention:seedling:) or ♻️ (:recycle:) for future improvements or indications of technical debt:pick:) for minor or nitpick changes