You all know that when you upgrade OS, all data is kept and usually everything works.

Because of some heritage espaces we couldn't upgrade directly our OutSystems, so we created a new server for v9 and all the new projects, and took this opportunity to redesign all espaces that we could. First advice: Don't do it. If they want the new amazing apps, the old website must be upgraded. Take my advice and take a stand. This "we'll do it slowly for a few months" never works because it's not a priority. I've been migrating in my "free" time for two years now... You have an idea of how those things go.

If you already made that mistake and moved to 10 before closing developments in 9, you may have noticed that it looks great on paper, but what about when you need to connect two espaces in different versions? How can you have different versions accessing the same data?

-Create an extension reading the existing SQL
-Adjust external keys in all entities.
-Reference the extension in espace and rename all entities [SQL table name] to [OS entity name].
That is almost the same as refering the espace.

The structure is already OS style so all the keys and data types are correct. If it was an upgrade, all validations in the espace still work.

SQL Queries can't simultaneously use Entities and Foreign Entities. You can have queries in both, but each query must exist in a single environment.
-It means you must externalize all related Entities, including Static Entities. And extensions don't have Static Entities, but I found a workaround for that, check below.
-Also, you can't just call User from your espace and use it everywhere. If you need User in internal and external queries, the extension must have a User table and the Reference entity will be something like User2.

How to work without Static Entities
The easiest way is to create site properties and functions to return the value.
Replace Entities.Status.Active with a call to StatusActive() that returns Site.StatusActive
and instead of Entities.Status.Deleted, StatusDeleted() returns Site.StatusDeleted

I made this in a new espace because the number or properties was quite big to keep.

Why in site properties? The Id's may change when publishing to a new environment. If they are in the code it means changing everything.

I hope this saves time to someone. I'll tell my particular case in the comments.

The story:
We had a major project (my bet is 2 years with 4 FTE) that couldn't wait for the complete migration. So while I, as the expert in all we had, am migrating v6, an outsource team is doing the new espaces.

It all went well until they needed the Workflows in v9. This particular application is nasty because although most documents are made in OS apps, it connects with SAP web services to read their states, and with OS apps to show the documents submitted. The migration could be easy if everything went to 9 at once, but that wasn't in the plan and workflows couldn't wait. So workflows was duplicated, one for v6 apps, one for v9 apps. But the way the services were implemented, we couldn't have both 6 and 9 connected to SAP simultaneously. Only one of them would receive the info.
Idea 1 - (in my defense, my background is middleware and integration, so I'm used to do strange things with data) OS server 1 connects to OS server 2 pretending to be SAP and passes the info forward and backward.
It went mostly ok, but the inbox documents appeared in outbox and viceversa. Two hours to implement, one week to debug and no conclusion.
Idea 2 - this one is a keeper. I just thought "if this were good OS, it would have worked." And eureka! I shouldn't think of it as an OutSystems espace, but as a native DB. I've created an extension reading the DB and OS9 is now working with v6's database. Either v6 and v9 change the same structure and call the same webservices, but not at the same time. When v6 dies, we can keep using that same DB or get all info from SAP directly and load its own entities again.