giip
SES Proposal
SQL ServerHighIOPSストレージEBSCDCログファイル移行コスト

Causes and Countermeasures for Disk I/O Performance Degradation After Migrating an On-Premises SQL Server to AWS

Published 2026-09-07 · Updated 2026-09-07 · Last Verified 2026-09-07

Answer

On-premises physical servers use PCIe bus-attached local NVMe/SSD with extremely low latency and high I/O throughput, but Amazon EBS, the standard for AWS RDS/EC2, is a virtual block storage attached via network, with IOPS and throughput strictly throttled according to instance size and volume type. Without understanding this difference, batches and index rebuilds stall due to throttling even when CPU headroom exists, and oversizing Provisioned IOPS only increases costs without addressing the root cause. The basic approach is to reduce the volume of disk I/O itself, with buffer pool maximization, data compression, physical separation of data and log files, and addressing CDC cleanup delays causing log bloat as the practical center of these efforts.

Applicability of This Document

ProductSQL Server (Amazon RDS for SQL Server / SQL Server on EC2)
Verified VersionsSQL Server 2012 and later (CDC-supported editions vary by version; verify)
EnvironmentAWS migration from on-premises physical servers (Amazon RDS for SQL Server, EC2)
Required PermissionsRead-only commands require VIEW DATABASE STATE or equivalent. db_owner (or sysadmin depending on environment) for manually running sys.sp_cdc_cleanup_job and executing DBCC SHRINKFILE
Execution ImpactRead-only commands only query. sp_cdc_cleanup_job deletes CDC change data; DBCC SHRINKFILE changes log file size
RestartNot required
Last Verified2026-09-07

Ready-to-Run Commands

Estimate space reduction from compressing existing tablesRead-only
対象
SQL Server 2008 or later / Amazon RDS for SQL Server
権限
reference permission on the target table (execute permission for sp_estimate_data_compression_savings)
変更作業
none (estimate only, does not perform actual compression)
Production実行
allowed
-- Target: SQL Server 2008 or later / Amazon RDS for SQL Server
-- Permission: reference permission on the target table (execute permission for sp_estimate_data_compression_savings)
-- Change: none (estimate only, does not perform actual compression)
-- Production execution: allowed
USE [SampleDB];
GO
EXEC sys.sp_estimate_data_compression_savings
    @schema_name = 'dbo',
    @object_name = 'Orders',
    @index_id = NULL,
    @partition_number = NULL,
    @data_compression = 'PAGE';

The difference between size_with_current_compression_setting and size_with_requested_compression_setting in the results indicates the estimated disk space reduction from compression. Compression reduces disk I/O at the cost of CPU overhead, so it is more effective in environments with CPU headroom.

Identify why the log is not being truncated (check log_reuse_wait_desc)Read-only
対象
SQL Server 2008 or later / Amazon RDS for SQL Server
権限
metadata visibility on sys.databases
変更作業
none (read-only)
Production実行
allowed
-- Target: SQL Server 2008 or later / Amazon RDS for SQL Server
-- Permission: metadata visibility on sys.databases
-- Change: none (read-only)
-- Production execution: allowed
SELECT name, log_reuse_wait_desc
FROM sys.databases
WHERE name = 'SampleDB';
-- If the result is 'REPLICATION', CDC or transactional replication is holding unread logs

REPLICATION can apply to both CDC and transactional replication. Check whether CDC is enabled on the target database with sys.databases.is_cdc_enabled. For details on tracking capture delays, see "How to check whether the CDC log scan has stopped in SQL Server".

Manually execute CDC cleanup (purge change data beyond retention period)Medium
対象
SQL Server 2008 or later (CDC-supported editions) / Amazon RDS for SQL Server
権限
db_owner (execute permission for cdc.sp_cdc_cleanup_job)
変更作業
yes (deletes data from CDC change tables beyond the retention period)
Production実行
allowed, but verify that downstream integrations are not still consuming the data to be deleted
-- Target: SQL Server 2008 or later (CDC-supported editions) / Amazon RDS for SQL Server
-- Permission: db_owner (execute permission for cdc.sp_cdc_cleanup_job)
-- Change: yes (deletes data from CDC change tables beyond the retention period)
-- Production execution: allowed, but verify that downstream integrations are not still consuming the data to be deleted
USE [SampleDB];
GO
EXEC sys.sp_cdc_cleanup_job;

This is an immediate workaround when the scheduled cleanup job is delayed. However, this addresses the symptom, not why the cleanup job itself became delayed (job stoppage, insufficient runtime, etc.) — investigate separately. Before executing, always confirm that replication targets or downstream ETL processes have not yet read change data within the retention period.

Shrink the transaction log (execute after cleanup completes)High
対象
SQL Server 2008 or later / Amazon RDS for SQL Server
権限
sysadmin or db_owner
変更作業
yes (truncates the end of the log file to reduce its size)
Production実行
generally allowed, but only after confirming log_reuse_wait_desc is NOTHING
-- Target: SQL Server 2008 or later / Amazon RDS for SQL Server
-- Permission: sysadmin or db_owner
-- Change: yes (truncates the end of the log file to reduce its size)
-- Production execution: generally allowed, but only after confirming log_reuse_wait_desc is NOTHING
USE [SampleDB];
GO
-- specify target size in MB to shrink to
DBCC SHRINKFILE (N'SampleDB_log', 1024);

Shrinking before resolving the log_reuse_wait_desc cause will result in immediate re-expansion. In this knowledge base, all SHRINK operations are marked as "high" regardless of impact level. For the difference between data file and log file shrinking and how to use TRUNCATEONLY, see "The difference between DBCC SHRINKDATABASE and DBCC SHRINKFILE, and what to check before running them".

How to Read the Results

ColumnMeaningWhat to Check
log_reuse_wait_descReason why transaction log space is not being released'REPLICATION' indicates CDC or transactional replication is holding unread logs. 'NOTHING' means there is no factor preventing release
size_with_requested_compression_settingEstimated size after applying the specified compression typeThe larger the difference from the current size, the greater the potential for disk I/O reduction and storage cost savings

When to Use This

  • Nightly batches and index rebuilds take two or more times longer, even with an AWS instance of equivalent or higher spec than the on-premises server before migration
  • The entire database becomes temporarily unresponsive during large-scale data loads or index rebuilds
  • Batches never complete despite CPU having available capacity
  • Storage capacity sharply depletes shortly after migration, triggering frequent RDS auto-storage scaling
  • Increasing Provisioned IOPS (io2, etc.) only drives up storage costs without achieving fundamental improvement

Possible Causes (Most Likely First)

  1. 01

    Latency inherent to network-attached storage (EBS)

    On-premises physical NVMe/SSD is directly attached via the PCIe bus and operates with microsecond-level latency, but Amazon EBS, the standard for AWS RDS/EC2, is a virtual block storage connected to the instance via a dedicated internal network link. Physical latency (in the order of milliseconds) is structurally unavoidable.

  2. 02

    IOPS and throughput throttling (bandwidth limiting)

    IOPS and throughput (MB/s) limits per second are strictly defined according to instance size, volume type, and allocated capacity. General-purpose volumes such as gp2/gp3 consume burst credits when exceeding the baseline performance, and reaching limits during large-scale data loads or index rebuilds causes severe throttling that can make the entire DB unresponsive. Even raising volume-side IOPS with io2 or similar may be bottlenecked by the instance-side EBS dedicated bandwidth (EBS-Optimized).

  3. 03

    Cost inflation from oversizing Provisioned IOPS

    When attempting to easily resolve insufficient I/O performance by heavily provisioning high-cost IOPS types such as io2/io2 Block Express, storage costs alone can balloon to hundreds of thousands to millions of yen per month, eliminating the cost-reduction benefits of cloud migration.

  4. 04

    Unreleased logs due to CDC cleanup job delay

    When large batch updates occur and the CDC cleanup job cannot keep up, the transaction log is marked as "not yet read by CDC," preventing log space from being released even after CHECKPOINT or log backups. The log file continues auto-extending, depleting storage capacity and forcing RDS auto-storage scaling to trigger.

Diagnostic Steps

  1. 1

    Estimate compression space reduction for existing tables

    Read-only

    Use sys.sp_estimate_data_compression_savings to determine how much disk I/O reduction and storage cost savings potential exists.

  2. 2

    Identify the cause of unreleased logs with log_reuse_wait_desc

    Read-only

    Check whether sys.databases.log_reuse_wait_desc is fixed at REPLICATION. If so, CDC or transactional replication delay is suspected.

  3. 3

    Check whether CDC is enabled and if capture is delayed

    Read-only

    Verify CDC status with sys.databases.is_cdc_enabled. If enabled, check capture delay with sys.dm_cdc_log_scan_sessions (see the related article for details).

  4. 4

    Verify EBS volume and instance IOPS/throughput contracted values

    Read-only

    Check the provisioned IOPS and throughput for the volume type (gp3/io2, etc.) and the EBS bandwidth limit on the instance side via the AWS console or CLI.

  5. 5

    Manually execute CDC cleanup

    Medium

    After confirming that downstream integrations have consumed all data within the retention period, execute sys.sp_cdc_cleanup_job to restore the log to a releasable state.

  6. 6

    Shrink the transaction log

    High

    After confirming log_reuse_wait_desc is NOTHING, shrink the log file to the target size using DBCC SHRINKFILE.

Solutions

Low-risk action that can be done immediately

  • Maximize the buffer pool to reduce disk reads

    Low

    Before paying to increase storage IOPS, scale up the instance size to increase RAM and maximize the SQL Server buffer pool size. Maintaining a state where frequently accessed active data remains cached in memory greatly alleviates the EBS I/O bottleneck.

  • Manually execute CDC cleanup to clear unreleased logs

    Medium

    Execute sys.sp_cdc_cleanup_job without waiting for the scheduled job, restoring the log to a releasable state. Verify downstream integrations have consumed the data before executing.

Change requiring advance review

  • Separate data files and log files onto different EBS volumes

    Medium

    Mixing data files (random I/O dominant) and transaction logs (sequential writes dominant) on the same EBS volume causes I/O queue contention. Always separate them onto different EBS volumes.

  • Apply PAGE/ROW compression to reduce I/O volume

    Medium

    When CPU resources are available, data compression reduces the block size read from disk and the size written to the log. Estimate the effect with sp_estimate_data_compression_savings before applying.

  • Offload read load with a read replica

    Medium

    If reporting queries and batch reads are straining the primary DB I/O bandwidth, build a read-only replica to distribute traffic.

  • Add CDC cleanup job lag to monitoring

    Low

    Monitor the success/failure and duration of the cleanup job to detect before the delay becomes chronic.

Change involving a restart or service impact

  • Shrink the transaction log with DBCC SHRINKFILE

    High

    Execute after confirming log_reuse_wait_desc is NOTHING. Shrinking without resolving the cause will result in immediate re-expansion. The operation consumes I/O during execution, slowing writes to the target.

Work requiring expert review

  • Redesign the need for Provisioned IOPS (io2, etc.) across the entire workload

    Expert Review Required

    Consider this only when IOPS remain insufficient even after buffer pool maximization, data compression, and file separation. Unplanned increases significantly raise monthly costs — have the I/O pattern of the entire workload analyzed and undergo professional review.

!Warnings

  • Before running DBCC SHRINKFILE, confirm that log_reuse_wait_desc is NOTHING. Shrinking while the cause remains will result in immediate re-expansion.
  • Before deleting CDC change data beyond the retention period with sys.sp_cdc_cleanup_job, verify that downstream integrations (replication targets or ETL) have not yet consumed data from that period.
  • Before casually increasing Provisioned IOPS (io2, etc.), first evaluate whether reducing disk I/O itself through buffer pool maximization and data compression is feasible.
  • The compression ratios and cost savings figures in this article depend on the workload and data content and are not guaranteed for all environments.

If This Doesn't Resolve It

  • Have you checked whether EBS volume IOPS/throughput burst credits are exhausted?

    Verify that gp2/gp3 burst credit balance has not been depleted using CloudWatch metrics.

  • Have you checked whether the instance-side EBS bandwidth (EBS-Optimized) is the bottleneck?

    Even raising volume-side IOPS will not produce expected performance if the instance EBS dedicated bandwidth limit has been reached.

  • Have you checked the CDC cleanup job execution history and errors?

    Verify that the cleanup job regularly succeeds and that there are no consecutive failures or skips in the job history.

  • Have you measured network latency including whether AWS Direct Connect is needed?

    Verify that communication latency between on-premises remaining applications and the DB on AWS is not another bottleneck.

Basis and Limitations of This Document

Content verified through real-world operations

This article generalizes Amazon EBS IOPS/throughput specifications, SQL Server CDC and DBCC SHRINKFILE public specifications, and trends commonly observed across multiple similar migration cases. Specific numerical values for compression ratios and cost savings are environment-dependent estimates and do not include specific customer examples or internal issue numbers.

FAQ

Is slow disk I/O after AWS migration always an instance sizing mistake?

Not necessarily. On-premises physical NVMe/SSD and AWS network-attached storage (EBS) have fundamentally different structures, and even selecting an equivalent-spec instance results in performance limits due to IOPS and throughput throttling. First consider designs that account for this structural difference: buffer pool maximization, file separation, and compression.

Does increasing Provisioned IOPS (io2, etc.) solve the problem?

It may solve the problem in some cases, but costs tend to escalate rapidly. We recommend first maximizing the buffer pool to reduce disk reads, then reducing I/O volume with data compression, and only considering IOPS increases if those measures are still insufficient.

Is the same response appropriate when log files are enlarging even though CDC is not in use?

log_reuse_wait_desc becoming REPLICATION can apply to both CDC and transactional replication. First check whether CDC is enabled with sys.databases.is_cdc_enabled. If CDC is not in use, refer to the transaction replication configuration or general log file usage verification procedures.

When is it safe to run DBCC SHRINKFILE?

When log_reuse_wait_desc has become NOTHING. If CDC cleanup delay is the cause, first execute sys.sp_cdc_cleanup_job to make the log releasable. Data file shrinking and log file shrinking have different impacts, so review the related articles before proceeding.

Questions This Document Covers

  • I want to know the cause of slowdown after migrating on-premises SQL Server to AWS
  • I want to know why storage costs surged after AWS migration
  • I want to know how to handle log files that keep growing due to CDC

What the Risk Labels Mean

  • Read-onlyDoes not change data or settings.
  • LowImpact is limited, but permissions and load should be checked.
  • MediumMay affect performance, locking, or cost.
  • HighMay cause an outage, data loss, or require recovery work.
  • Expert Review RequiredRequires a separate review before applying to production.

GIIP's Scope of Support

Alerts based solely on resource threshold values such as "Disk I/O exceeds 90%" cannot reveal which queries or processes are causing the I/O pressure or how much unnecessary cost is actually being incurred per month. GIIP retains storage I/O, IOPS consumption, CDC cleanup job execution status, and log file changes in the same time series, enabling root causes to be identified on a cost ($) basis. Decisions that are irreversible and high-cost, such as Provisioned IOPS increases, are operated on the basis of having a human confirm the SQL and rollback procedures to be executed beforehand.

Author & Technical Review

GIIP Production Operations Team

About 30 years of experience in designing, migrating, and operating large-scale web services, SQL Server, Oracle, AWS, and Azure. Experience includes 12 sets of x12large-class AWS RDS for SQL Server environments, an Oracle environment with roughly 120,000 tables, and migrating roughly 3TB from TiDB to Aurora MySQL. AI agents and human experts currently continue to monitor and operate multiple cloud databases and about 30 web services.

Related Knowledge

Related Services

Diagnose disk I/O performance after an AWS migration

If you need to repeat the same checks across multiple environments, we can discuss your entire operations setup.

Diagnose disk I/O performance after an AWS migration

← Back to Knowledge Base