Once an application is designed and at least partially implemented, options for scalability and portability are reduced. If a system’s usage profile can not be predicted, then deploying to physical servers is a real problem because you have to pay for support for peak usage periods – however, relying on cloud infrastructure can very much limit platform portability.
It helps to consider scalability up front! Relying on scalable data store infrastructure like Googles AppEngine datastore or Amazon’s SimpleDB can make life easier. For server side Java, coding to JPA makes it possible with some work to be portable between AppEngine datastore, SimpleDB, or using a traditional database on your own server. Some care needs to be taken to code to a subset of JPA (e.g., no cross domain queries in SimpleDB) if portability is important. In the Rails world, using Datamapper provides similar flexibility for portability between AppEngine datastore, SimpleDB, or a conventional database. And, taking this approach fails when you need a relational database.
Using asynchronous messaging is anther good strategy for scalability (and for decoupling). With some care, applications can be somewhat portable between AppEngine’s Task Queue API, Amazon’s SQS, or running something like RabbitMQ on your own servers.