As of the first of November, ENKI will begin offering provisioned-performance storage (PPS), which allows you to decide how much storage performance you need for your virtual machines (or volumes) by requesting a guaranteed level of performance. Although a number of cloud providers offer provisioned-performance storage as an option, many customers don't fully understand the advantages that it offers for trading off your costs versus application performance for storage-intensive applications such as databases.Prior to provisioned-performance storage, or with some PPS offerings that cannot actually guarantee a large range of storage performance, the cloud customer basically had only one variable to adjust when application response time was dependent on storage performance, which was the allocation of memory to the database or perhaps to a caching application. By storing more of the critical data that application needed regularly (called the "working set") in memory, accesses to storage could be avoided, allowing the speed of the application to decoupled from storage speeds. However, this is a very expensive approach, since large databases would require large amounts of memory.With PPS, the customer now has the ability to vary storage speed as well. The resulting speed of the application will depend proportionally on the amount of storage performance (usually measured in IOPS - input/output operations). However, adjusting memory size will still have an effect and in many cases should be the first thing that you try. The reason for this is that if your application's working set doesn't fit into memory, then most of the requests for data that it creates will require a storage access. Since storage is many times slower than memory, this will cause your application to lose a large portion of its potential performance.I found the following quote on the web recently:"A well designed web application should serve 99% of its queries out of memory"What this means is that you must determine your working set size by using appropriate diagnostic tools on your database, and then allocate enough memory to keep that working set completely in your server. It also means that you need to design your database schema to partition your data in such a way that a working set can extracted from the total amount of data you are storing. This may not be practical for some applications (especially "Big Data" applications where much of a very large database must be scanned to generate the answers required) but I think it's a good general rule. In the chart above, we see a typical storage speed/memory optimization curve. On the right, the memory is being increased and results in a sudden increase in application performance as the entire working set is now cached on the server. Increasing memory beyond that point only increases application performance slightly, since it caches less frequently-used data.On the left, the storage performance is being increased. Here, a linear increase in storage performance results in a similar linear increase in application performance. A good practice is to choose a level of storage performance that results in acceptable application performance after you have found the amount of memory that is required to store your working set. These rules are general, but also universal: you can't beat this effect even if you divide up your storage into smaller chunks and certainly not if you increase CPU speed on your database instance.