← ResourcesMIGRATION Β· PERFORMANCE

Post-Migration Infrastructure Performance Optimization

Diagnose compute, network, and storage bottlenecks to recover your SLAs in production.

STRALYA13 min readJuly 2026

Why performance collapses after a migration to AWS After a migration to AWS, it is common for an application to perform worse than expected, even when the infrastructure appears correctly configured in theory. This phenomenon rarely stems from a single failure but rather from a combination of factors often overlooked during the transition phase. First, many migration projects keep the sizing of the source environment without adapting it to the real capabilities of the cloud. A database that ran on a physical server with 256 GB of RAM benefited from operating-system caches and predictable network behavior. As soon as it runs on an AWS instance (even bare metal), network latencies, contention on shared resources, and the absence of cache warm-up create unexpected bottlenecks. Second, legacy architectures designed for centralized data centers do not take advantage of AWS geographic distribution and native capabilities. An application that issued 500 network requests per user request on-premise, because it communicated over very fast private buses, suddenly becomes vulnerable to inter-service latency in the cloud. Finally, during the migration, energy is focused on service continuity and functional validation, not on performance tuning. The default AWS configurations (pooled connections, timeouts, cache TTL) almost never match real load profiles. Understanding this transition calls for methodical analysis rather than random adjustments. ## Identifying the real performance bottlenecks Before changing anything, you must establish a precise diagnosis. Most teams ask "why is it slow?" without knowing where to investigate. The answer lies in four axes of observation: CPU, memory, network, and disk. For CPU, CloudWatch Metrics provides the raw data (CPU utilization, CPU credit balance if you use T3 instances), but that is not enough. An instance at 25% average CPU utilization can be completely saturated if that 25% is concentrated on a single core. Use AWS Systems Manager Session Manager to access instances and run tools like top, htop or, better, perf or flamegraph to identify the functions that consume the most CPU. For memory, CloudWatch does not report the operating system's native memory-pressure metric. Install the CloudWatch Agent with the Custom Metrics configuration and send mem_available, mem_used_percent, and swap_usage. Spikes in pressure with no visible increase in CPU indicate an application memory leak or excessive process concurrency. The network is often the forgotten culprit. Check the CloudWatch EC2 metrics for dropped packets (PacketsIn/Out, NetworkPacketsIn/Out) and the real network throughput. Use iftop or nethogs to trace where network connections come from. An application that opens a new TCP connection for every request (instead of reusing a connection pool) can choke the network, especially across availability zones. Finally, for disk, EBS CloudWatch metrics (VolumeReadBytes, VolumeWriteLatency, VolumeQueueLength) reveal whether storage is becoming a bottleneck. If EBS write latency regularly exceeds 100ms, or if the queue builds up, the disk is saturated. Some cases require deep application analysis. If your application is multi-tier, use X-Ray to trace latency per service, thereby identifying the steps that take abnormally long (a blocking network call, an inefficient database query, or inefficient business logic). An unbiased analysis means consulting the application logs (via CloudWatch Logs or a third-party aggregator) to spot hidden errors, retries, or timeouts that slow things down in a cascade. ## Compute sizing and choosing the optimal instance Once the bottlenecks are identified, the next step is to adjust the compute. In companies, three common mistakes sabotage this phase. First, increasing the instance size is never the only solution, but it is often the first one attempted. If a CPU-bound application consumes 80% of the resources of a t3.xlarge, moving to a t3.2xlarge will temporarily double the capacity but will not address the root cause: why is the algorithm inefficient? Second, confusing stateless and stateful instances creates disasters at scaling time. A database with in-memory state cannot simply be placed in an auto-scaling group; each instance loses its data. Third, ignoring AWS discounts (Reserved Instances, Savings Plans) leads to unjustified costs after optimization. To size correctly, follow this approach: measure the real load with application profiling (Apache JMeter for web apps, sysbench for databases, or X-Ray traces for distributed services). Determine the number of requests per second, the target latency, and the percentage of CPU/memory your application can consume without degradation. Then map these needs to an AWS instance family. If your load is CPU-intensive, c6i or c7g (compute-optimized) instances offer the best ratio. If it is RAM-intensive (in-memory cache, data warehousing), prefer r6i or r7g (memory-optimized). For highly parallel workloads with frequent network access, d6i or m6i (general purpose) instances are versatile. Do not stop at the generation. The latest generations (c7, m7, r7) consume less power, offer faster processors, and reduce costs. Always compare the total annual cost (TCO) on a spreadsheet: a c7i.2xlarge that is more expensive up front can cost less than a c6i.4xlarge over a year if it reduces the scaling needed. Finally, test your candidate on a single instance under real load (not synthetic) for at least one hour. Observe CPU, memory, network, and application latency. If the metrics stay within acceptable margins and the application responds within the SLAs, you have your answer. If load spikes send a metric beyond the thresholds, try the next size up or investigate a real application-architecture problem. ## Optimizing network configuration and inter-service latency The network is one of the most underestimated sources of slowdown after a migration. Teams often provision instances in a single availability zone (AZ) for simplicity, without realizing that this creates a single point of failure and increased latency if traffic has to cross a spine router. A network diagnosis starts with checking the VPC topology. Use VPC Flow Logs (CloudWatch) to observe connection patterns. If 90% of the traffic leaves the VPC to the Internet Gateway, then comes back through NAT (an inefficient pattern), reconsider your design. The Security Group configuration deserves attention: rules that are too permissive slow down the application firewall; rules that are too restrictive cause legitimate requests to be rejected. Validate that all expected flows (databases, caches, internal services) are allowed with the correct CIDRs or security groups. For distributed applications, reducing inter-service latency is critical. If your frontend application calls a backend service over the internet, you cross the Internet Gateway, then come back in via NAT. The good practice is placement in the same AZ or VPC (same region preferably) with security groups that authorize each other, rather than going through a public IP. Use AWS Systems Manager VPC Endpoints for AWS services (S3, DynamoDB, CloudWatch) to avoid the Internet Gateway. A VPC endpoint for S3 reduces latency by 50-100ms (round trip) in typical cases. For third-party services (external APIs), where possible, cache the responses locally or use a CDN (CloudFront for AWS) rather than calling the external service on every user request. The MTU (Maximum Transmission Unit) size of network packets also affects effective bandwidth. By default, AWS uses 1500 bytes (standard internet MTU), but instances in the same VPC can use Jumbo Frames (MTU 9000) to reduce the number of packets and increase throughput. If your application does large transfers (database replication, backup), test this configuration. Finally, Enhanced Networking (EN type, for example Intel 82599 or ENA) doubles or triples network throughput compared to the standard virtual network. Make sure your instance type supports ENA and enable it via the instance's network attributes. ## Tuning caches and memory allocation to reduce database calls After a migration, data access patterns change. In a physical environment, centralized data centers offer very predictable disk latencies (under 10ms for local SSD). In the cloud, data stored on EBS lives on a virtualized network, which adds 5-20ms of extra latency depending on the configuration and contention. This latency multiplies with every database query. If an application issues 50 queries to display a page, and each query takes 20ms (10ms network + 10ms disk), the page takes at least 1 second to load, before even counting the application time. The classic solution is caching. ElastiCache (Redis or Memcached) can reduce this latency to 1-5ms for a cache-hit read. Redis is preferred for complex data (structures, rankings), Memcached for simple, very high-performance key-value. Size your cache cluster based on the real working set, that is, the fraction of data accessed regularly. If your database is 100GB but only 10GB is requested per hour, a 15GB Redis cache (with 50% headroom) is enough. Measure the hit rate: if fewer than 80% of requests are cache hits, increase the size or review your invalidation strategy. For the databases themselves, tuning the parameters is critical. RDS offers parameter groups that control cache buffer, query timeout, parallelism, and so on. A poorly configured RDS MySQL with a default buffer_pool_size (128MB) on an r5.2xlarge (512GB RAM) wastes 95% of your RAM. Increase the buffer pool to 80% of available RAM and observe the cache hit ratios (for example, InnoDB_Buffer_Pool_Reads vs InnoDB_Buffer_Pool_Read_Requests). Ratios below 95% indicate that your cache is overloaded. Finally, query structure matters. A query that scans an entire table and filters in memory rather than using an appropriate index consumes enormous resources. Spend time analyzing the slow queries (via RDS Performance Insights) and create the missing indexes. Often, indexing 2-3 key columns reduces query times by 10x and cuts the database's CPU/RAM load proportionally. ## Monitoring and continuously tuning performance SLAs Optimizing once is never enough. Load patterns change, new features slow the application down, or a colleague deploys an inefficient query. A continuous monitoring process with clear SLAs (Service Level Agreements) is therefore indispensable. First define concrete application SLAs: the percentage of web requests that must respond under 200ms (p95), the maximum duration of a critical database query (500ms), the data replication time (RTO, Recovery Time Objective). These figures must be realistic (not 10ms if your network has 50ms of latency) and shared with the business so everyone understands the goal. Then, instrument your application and infrastructure to measure these SLAs. CloudWatch Synthetics creates artificial tests (canaries) that simulate real users and alert if an SLA drifts. For RDS databases, enable Performance Insights (included in RDS) and examine the slow query logs (slow_query_log in MySQL, long_query_time threshold). Configure CloudWatch alarms for: CPU > 80%, memory > 85%, p99 latency > SLA threshold, packet loss > 0%, EBS queue length > 1. These alarms must trigger an action (email, SNS topic, or a call to the escalation process). Establish a weekly or monthly routine (depending on the pace of change) to review the metrics. Ask the questions: "Did we meet all the SLAs last month?", "Which queries became slow?", "What code was deployed that explains a change?". If an SLA is not met, look for the cause systematically (using application logs, X-Ray traces, or application profilers) rather than blaming the infrastructure. Finally, plan future optimizations: if you are approaching 80% CPU capacity, plan the scaling before a crisis. If the cache cost explodes, investigate why the working set is growing. This iterative, data-driven approach prevents degradations and maintains performance over the long term.

AWS TEARDOWN Β· FREE

Get the AWS Teardown: where your bill really goes.

The guide listing the 12 cost areas that leak the most at scale-ups, and how to plug them. Free, by email, no obligation.