Compatibility is extremely important to Silverlight, so how exactly do we achieve it?  Before we get into that, we need to take a moment to define different types of compatibility. The most important is application compat -- if you have a xap written for SL2, it should run unchanged when you run it with the Silverlight 4 plug-in.  (SL1 doesn’t have xaps but similar concepts apply to SL1 applications)  Our goal is to never break applications, even if they are doing things the wrong way or relying on undocumented behavior, and while there's not much we can do about the app that uses reflection to enumerate all properties and crashes when it encounters new ones (really happened!), our experience with SL1/2/3/4 is we get pretty close to that goal.
 
Another kind of compatibility is upgrade compat -- when you take a Silverlight 2 app and recompile it against SL4, does it still work? Similarly, can you take a control library developed for SL2 and use it unchanged in my SL4 application?  This isn't quite as important to us as application compatibility – if fixing a bug means breaking upgrade compatibility, we’ll fix the bug -- but it's something we keep in mind with every change we make. 
 
Quirks mode
 
In order to support older applications, Silverlight has the concept of "quirks mode". In quirks mode, Silverlight tries to be bug for bug compatible with the previous version. (Actually, there's more than one quirks mode -- quirks mode for SL2, quirks for SL3, etc)  When the SL4 plug-in runs an application developed for SL3, Silverlight detects what version the xap was designed for & goes into the appropriate quirks mode.
 
Of course, each quirks mode bug is also an upgrade breaking change -- if your application depends on that bug, when you upgrade your app, you'll need to stop relying on the old behavior.  In order to facilitate this, the Silverlight team documents the differences between quirks mode and normal mode, see http://msdn.microsoft.com/en-us/library/cc645049(VS.95).aspx
 
It would be too unwieldy to quirk every last change and bug fix that goes into Silverlight.  But we err on the side of caution and quirk anything that may affect a functional real-world application. To keep things simple, we don't quirk issues that would only affect test cases not real-world apps, nor do we worry about changing a broken app into a different kind of broken app. (E.g., the app used to kill the browser, now it crashes with an unhandled ArgumentException)
 
Another key to compatibility is testing.  With each release of Silverlight, we run hundreds of apps to make sure they behave the same.  We test a broad mix of apps developed internally and provided by customers and partners.
 
Side by side
 
While we don't support side-by-side everywhere, we do use side-by-side technologies in certain places.  The most obvious is the SDK, you can have SL SDK v2, v3, and v4 all on the same machine. And when your application uses an SDK library, the exact version you built against is included in your xap – an SL3 app using DataGrid will use the SL3 implementation, even when running on the SL4 plug-in.
 
We also use side-by-side under the covers to implement some really big quirks.  SL4 for instance contains both a old SL3-compatible parser and a new SL4+ parser, because we knew there were too many parser changes to try to quirk them each individually. Similarly, there's an old & new text engine, and SL4-mode enables a slew of JIT codegen optimizations that aren’t done on SL2 & 3 apps.
 
From time to time, we wonder if it would make sense to go all the way with side-by-side like we do with the .NET Framework and allow multiple versions of the Silverlight plug-in to be installed.  Never say never, but we don't think side-by-side makes sense right now for a few reasons:

  • Users want to install one thing that lets them run all Silverlight content. They don't want to install three or four different plug-ins, and they don't want one plug-in that's three or four times bigger than SL4.
  • In-place updates keep servicing costs down.  When a new browser or operating system is released, we only need to make the change once, in the latest version of Silverlight.
  • Everyone runs the latest version of the Silverlight plug-in.  So everyone writes apps for the latest version of Silverlight. And ISV’s and control vendors can target that latest version and not worry their customers will demand an SL2 version.  You can also reduce if not completely eliminate some mix-and-match concerns -- What happens if an SL4 app tries to load an add-in that's written for SL5?  What happens if an SL4 app serializes a file that an SL3 app tries to read? 
  • Similarly, less mix-and-match simplifies things for Silverlight. For instance, we don't have to worry about what happens if an SL4 plug-in uses LocalMessageSender to communicate with an SL3 plug-in -- under the covers, the shared memory protocol we use is implementation-defined, and we can change it between versions because there's only one version of Silverlight on any given machine.

So that's the inside scoop on how we keep Silverlight compatible with previous versions. As usual, we'd love your feedback so we can build a product that works best for you. Thanks.