Skip to main content













Traditional to Reactive App migration reference

This document is a work in progress and we invite you to send us your feedback.

This document is intended for experienced developers and leads as guidance in migrating Traditional Web Apps to Reactive Web Apps. The migration requires good knowledge of the new front-end features and knowledge of the application architecture. Check our training Becoming a Reactive Web Developer for an introduction.

We provide this reference document as a collection of notes about the differences between Traditional and Reactive App. The purpose is to help developers in migrating an existing Traditional app to a Reactive runtime.

In this document we use the following terms:

  • source - refers to the existing Traditional Web App we're migrating from
  • target - refers to the new Reactive Web App we're migrating to

Preparation and initial planning

These are the considerations relevant in the preparatory steps of the Traditional Module migration.

  • URLs should be working for new Screens, Resources, Images. If you use hardcoded URLs, you need to update them in your new Screens.
  • Migrate Entities while preserving the data
  • Handling Site Properties
  • Migrating Roles
  • Impact of Timers and Processes

Once you start migrating your app to the Reactive App, we suggest the following order:

  1. Theme
  2. UI Flows
  3. External sites
  4. Screens
  5. Blocks (in order of dependency)


There are several accelerators that can help you migrate your app faster.

Copy and paste

You can copy the following elements from your Traditional App to Reactive App:

  • Server Actions
  • Entities

Additionally, you can:

  • Paste a Server Action to a Screen Client Action, but only the elements that work are preserved.
  • Paste Aggregates to a Screen to create a Screen Aggregate.

Scaffolding and Screen Templates

If your Screens are based on scaffolding or Screen Templates, it is faster to recreate them the same way. Makes sure you're using the latest version and try out different scaffolding patterns.

Module Elements

Here is an overview of the elements that are relevant to the module (eSpace) level of migration, with details on how to approach creating new logic in Reactive App.


When migrating logic that deals with Entities to the target app, pay attention to those which you need to make public or set Expose Read-Only to false.

Creating a new Entity in your target app creates a new physical table. With this in mind, the suggestion is to change the Entity to be public, then add a reference to it in the target module.

You can also use the accelerators for migrating Entities (copy and paste them).

Multilingual Locales

We're working on improving this feature. Occasionally during page refreshes the locale settings can reset to English.

For the client-side UI and client-side logic use Multilingual Component from Forge. Extract the text from the source module into the spreadsheet and convert it to the format needed for AddTranslations or AddTranslationsFromResource. Determine (e.g., by searching for uses of the translated text) which translation keys correspond to which elements and add data-trans attributes or GetTranslation calls where possible.

For the server-side logic use the built-in GetCurrentLocale function and explicitly inline the translations.

On Session Start

Use On Application Ready Event in Reactive App to set the initial values of Client Variables as the configuration parameters in the app.

When On Session Start is used in the source app to initialize the Session Variables, migrate the logic in the target app in a place where the variables are read, and protect it by checking if the variable is defined. For example, if you're using Cookies, add the logic before calling GetCookie, so it runs only if the Cookie was not set before.

If On Session Start is used otherwise in the source app, it needs to be evaluated case-by-case. Take into consideration that this logic runs on the first server request and when a user logs in and on the first request after having logged out.


Change the Process to be public in the original module and reference the Process, to avoid losing data.


To avoid losing data, change the Role to be public in the original module and reference the Role. Afterwards, confirm that all the Screen permissions are the same.

Server Action

The way you migrate Server Action to the new app depends on whether the Action is public, its use in the Screens, and whether it can be used client-side in the new Reactive App. Check the accelerators section to learn how you can use copy and paste with these Actions.

Not used a function

You can migrate it directly to Server Action in the target app.

Used as a function with input parameters

Migrate this Action so that it is called after the input parameters are calculated, typically at the end of a Data Action. Create a Data Action with an output for each Action. The Data Action should call the Server Actions in the order that they were used in the Screen.

Used as a function with a constant number of times in a Screen

The Server Action is used a constant number of times on the Screen (not in a List). Migrate the Action to Server Action in the target module while creating a local variable for each function call.

Used as a function with a variable number of times in a Screen

The Server Action is used a variable number of times on the Screen (in a List). Migrate the Action to Server Action in the target module. Then, add a calculated Attribute in an Aggregate that creates the list that calls the function.

Session Variable

Client Variables in Reactive are in many ways similar to Session Variables. Use Client Variables with the On Application Ready Event to initialize global configurations for the apps, like instantiating username, locale, filters.

Keep in mind:

  • The value of a Client Variables is cleared when the user signs out
  • On Application Ready System Event is triggered every time you run the app in a new tab/browser

The migration a Session Variable depends on whether the variable is tied to a browser session or user preference, its data type, and whether they may contain confidential information.

Site Property

To preserve their current values, copy the values from the original module to the new one, via Service Center.

Tied to a browser session

If the Session Variable is tied to the browser session and the data type is simple, migrate it to a browser-session-lived Cookie using some name convention (e.g., SessionVariable_NAME). Keep in mind that the values are not cleared on log out.

Replace reads and writes by the GetCookie and SetCookie methods of HTTPRequestHandler.

Alternatively, for better client-side read performance, use a JavaScript Node to get the cookie value from document.cookie.

If there're widgets bound to the variable, create a Local Variable to bind them to and then sync the value with the Cookie.

Note that the data type distinction is important because Cookies have limits, and storing complex types there can be extremely inefficient.

Used for storing a user preference

If the variable is used to store a user preference (i.e., it is tied to the user, not the browser session):

  • If it is only used in the UI/client-side logic store the value in a Client Variable
  • If the Session Variable is used by the server side, migrate the variable so the logic uses a row in a database Entity, associated to a User Id.

Additional work might be needed for variables of List and Record data types (e.g., you may need to devise an encoding, use a separate table...).


If the Session Variable use case is not described in this section, then the migration needs to be evaluated case-by-case.


Copy the CSS you need from the source app into the Theme of the target app.

UI Flow

The new UI FLows of the target app should point to the new Theme. The advanced properties HTTP Security, Integrated Authentication, and Internal Access Only cannot be migrated.

UI Flow elements

Here is an overview of the UI Flow elements and tips on the migration.


There is no conversion for this element. In the target app, right-click a Screen in the Elements Tree and select Mark as Default Screen to set the Screen as an "entry" point to a module.

External Site

Migrate the element to the External Site in the target app. All the input parameters and properties should have a direct mapping.

Pay attention to the External Sites with relative URLs to different modules, as these may fail due to different URL endings (there's no more .aspx or .jsf). The relative URLs to different modules are now handled by an internal router, so the full URLs need to be used.

Flow Exception Handler

The OnException handlers are on the client side. For the server-side errors you need to use the exception handlers on the flows if you want to handle the exception server-side. If you don't mind having exceptions bubbling up to the client-side, then you can handle them either on the client-side Action that called the Server Action or on the OnException handler on the UI Flow.

Check also the recommendations for Screen Actions.


You should create new Screens in your target app or reference them from other modules, with the following in mind:

  • You should not store sensitive information in Local Variables.
  • As the UI is generated on the client side, the Screens shown before the Role validation.
  • Where possible, transform JavaScript logic to a logic that uses Client Actions.

The Title property needs to be transformed to the text value instead of an Expression.

Name, Description, and Screen Roles can be the same as in the source app. Migrate the JavaScript property to the new JavaScript element.

HTTP Security, Integrated Authentication, and Cache In Minutes have no mappings in the target app. Note that HTTPS is enabled by default.

Web Block

Check the introductory notes for Screen.

Notify and NotifyGetMessage are not available in Reactive Web. Use Events and create corresponding handler Actions.

Referenced Web Block

Insert them through dependencies.

Screen and Block Logic

Here are details on how to migrate logic in your source Screens and Blocks to your new Reactive app.

Ajax Refresh

The UI elements in the target module refresh automatically on data change, so the Ajax Refresh is not needed.

Download node

Use the new Download node by adding it to the logic flow.


Preparation is one of the elements not available in the Reactive App and you need to refactor this dedicated Screen Action. You should be careful not to replicate the Preparation logic in a way that slows down the app, for example, by forcing the client-side to wait for the server-side response.

Instead, evaluate the use cases:

  • Are you're fetching data only to show it in the UI? Use Screen data Aggregates and bind the result to your Widgets. Aggregates run asynchronously and in parallel, and your UI updates when the Aggregates finish fetching data.
  • Are you manipulating data before showing it? Use Data Actions to manipulate the data to fit your needs, and then send the right information back to the client side.

To get data to a Screen in a Reactive app, right-click a Screen in the Elements Tree and select Fetch Data from Database or Fetch Data from Other Sources.

Max Records

Don't forget to address Max Records in the target app, as its value is calculated in the source app from the widgets they're bound to.

Aggregates with no dependencies (or dependents) can be moved to Screen Aggregates. If the Aggregate Max Records is empty, it should be entered as the value:

  • If bound to a single widget, of the Line Count of that widget
  • If bound to multiple widgets, of the highest expected Line Count

Refresh Data

When migrating the Refresh Data node, you need to analyze the dependencies between the data sources and how data is used in the Screen. You also need to check that the client side in the target module receives only the data it requires, ensure that your app is not exposing confidential information.

If the refreshed Data Source doesn't have dependencies, then the logic should be isolated, in a Screen Aggregate or a separate Data Action - and then refreshed.

If there are dependencies between the data sources, consider using the Fetch property of Aggregates (On Start and Only On Demand) and creating dedicated async patterns. You can check an example in the document Implement asynchronous data fetching using Aggregates.

Send Email Tool

This feature is currently not available in Reactive, but we're working on it. In the meantime, here are some workarounds:

  • Reuse logic from your Traditional App
  • Use a third-party service

Screen Action

Keep in mind the app performance when refactoring your Screen Action logic. Identify which logic should run on the server, and which on the client. You should then separate the logic into Server Actions and Client Actions. You may need to have input parameters for your Server Actions, depending on how you change the Screen in order not to use the Preparation.

You can't use the following actions directly from UI, as they imply direct access to the server runtime:

  • System Actions where there's no client-side alternative, which includes transaction- and login-related Actions.
  • Check/Grant/Revoke roles. Note that there's a JavaScript API for checking roles, but you should be careful when using it, as your apps must be secure and by default allow only the information relevant to the current Role to be fetched by the client-side.
  • Aggregates on server Entities.

Systems Actions

If there's no equivalent Client Action to the Server Action you want to use, consider:

For more ideas and examples, check the Reactive Utilities Forge component by our community.


Check Web Block.

Notify Get Message

Check Web Block.


When creating new UI experiences in the target app you should keep in mind the client-side development paradigm and the differences outlined in this section.

General considerations

These are the considerations applicable to all Widgets.

Min. Height, Width, Height

In Reactive, use the "style" extended property. For example: min-height: 15px;. If Width is set in chars, set the length in em as an extended style property.


The Style property is Expression in Reactive Web App.


You should not use the Visible property of the widgets to hide sensitive information.

In Reactive Apps the interface is primarily rendered on the client side, before the checks against the defined user roles. Be careful when migrating Widgets to the target app and check if the right information is delivered to the right client-side.

Widget comparison overview

This section contains notes about the widget differences. Here is the table with the Traditional Widgets and their Reactive Web counterparts, where available.

Traditional Web Reactive Web
Button Button
Checkbox Checkbox
Combobox Dropdown
Container Container
Comment NA
Edit Records Form
Editable Table Table with inputs inside cells
Expression Expression
Form Form
If If
Image Image
Input Input, TextArea
Input Password Input
Label Label
Link Link
List Records List
Placeholder Placeholder
Radio Button (in development)
Show Records Table
Table Records Table
Text Text


Convert the Display property to a "style" extended property with if(<expression>, "", "display: none;").


You should use Dropdown Widget in your target apps instead of Combobox. You can use Options Content with Text Only to generate <span> elements or Custom to generate <div> elements for more flexibility.


Expressions should be straightforward to implement. If you used Escape Content option in Traditional App, for inserting HTML tags use the HTML Element in Reactive.


Check an example on how to Validate Form Inputs.


Ensure that you're not bringing confidential information to the conditions of the If Tool. For example, if you have information visible only to admin on the server-side, reusing the same logic in the target app could fetch confidential information to the client-side UI of the Reactive app.


The Label property is not available in the Reactive Image Widget. Use the Extended Property "title" to set the title of the image.


You can use Reactive Input Widget or TextArea Widget. If you need a password field, use Input Widget and set the Input Type property to Password.


In the Reactive App, the Label Widget contains only Text property with a text value.

List Records

Use List in the target app. The Line Separator impacts the widget generation:

  • None: The Mode property set to Custom, with a span tag.
  • New Line: The Mode property set to Custom, with a span tag and a trailing Text widget with a "\n" text.
  • Bullets: The Mode property set to Custom. Needs an enclosing HTML Element with a span tag. You also need the ul tag with another HTML Element (with the li tag) for each list element.

Radio Button

This Widget is currently in development.

Show Records

See Table Records


See Table Records

Table Records

The Table Widget in Reactive App is a new widget that supports scaffolding, pagination, and sorting for tabular data. Check the documents Creating and editing tables and Table pagination and sorting.

Rich Widgets overview

Rich Widgets are legacy built-in widgets that are not supported in OutSystems UI. We replaced them with more modern implementations in Reactive App. Use this table for guidance on how to replace Rich Widgets in your new app.

Rich Widget Notes
Application Switcher Change Data Source to Data Action.
Dropdown Menu Use the Dropdown Widget from OutSystems UI.
Feedback Ajax Wait No Ajax in Reactive, review the UX and update it.
Feedback Message Use Message Tool on client side, fetching message from server if needed.
Icon Use new Icon, with Size instead of Font Size.
Input Autocomplete Migrate to an Input Widget with OnChange login or DropdownSearch from OutSystems UI.
Input Calendar Use the Date Picker Widget from OutSystems UI.
List Counter Create your own or check the Pagination Widget from OutSystems UI.
List Navigation Check the Pagination Widget from OutSystems UI.
List Sort Column Scaffold a Table with sorting and inspect the logic, reusing and adapting as needed.
Layout Chicago / Email / Popup Use Blocks.
Layout London Use Block and light UI.
Popup Editor Use PopOver Menu and Popup.
Popup Info Balloon Use PopOver Menu and Popup.

Widget Events

Here are the migration notes about Widget Events.

On Click

The functionalities of On Click set of properties in Traditional Web can be implemented in Reactive app like this:

  • Destination - point to Screen Action or Screen
  • Validation - use the Built-in Validation to check on the client side, but also implement validation on the server side before committing any values to the database
  • Method Submit or Ajax Submit - set to Screen Action calling a referenced Server Action from the source app (reuse old logic)
  • Navigate - redirect to another destination
  • Was this article helpful?