Architecture of generated apps
Table of contents
OutSystems includes a unique deployment engine capable of generating and deploying standard web or mobile hybrid applications from a comprehensive set of visual models
This approach allows developers to focus on modeling their applications in a way that best suits particular business requirements, supports integration with other services or technologies, and ensures continuous functionality, security and performance updates via our optimized code-generation technology.
OutSystems standard architecture with no lock-in, ensures that your IP and investment is protected in case you ever wish to discontinue your OutSystems subscription.
Without requiring any proprietary components, runtime engines, or interpreters, applications are generated into a fully open, standard, optimized and documented set of server and client components, deployable to a standard web server.
The OutSystems compiler is an ever evolving component because target architectures are also in constant evolution. We employ best practices for performance and continuous updates on the security of your applications.
The modular architecture of the OutSystems platform makes it easy to generate new architectures. This ensures that:
- If a vendor discontinues the support for one of the technologies we use, that change won't affect your applications.
- Developers are isolated from constant technology shifts and breaking changes in the underlying frameworks.
- Your applications benefit from new technologies and frameworks that will bring all kinds of non-functional improvements
Independent of the languages and architecture in which applications are generated, we are constantly working so that they run with the highest quality, performance and security - you benefit from this abstraction and all the best practices employed by our expert engineers and architects, and your end-users benefit from higher quality and higher performance applications.
High level application architecture
Applications created with OutSystems include three types of components: generated, runtime and custom backend extensions.
The following diagram shows how an application is split into its underlying components:
These components are created automatically whenever an application is submitted for compilation and publishing. The generated components include:
- REST APIs and SOAP web services are directly generated and exposed as backend endpoints. The corresponding contracts (.json Swagger or .wsdl files) are also generated. In addition, a set of REST APIs are automatically created by the platform as the backend services for your mobile applications.
- The backend / server logic that supports your business rules, background job logic, and APIs are generated as optimized server code. Proxies to other referenced applications are included in the backend logic as assemblies. This abstraction means apps reusing the services are unaffected when the implementation of the service changes.
There are a set of components included in every application that support the base functionality, including base rendering capabilities and access to various services within the OutSystems platform:
- Generic Platform Library: Client or Server side classes and methods used in all generated applications, such as the OutSystems built-in functions available in Service Studio, database connection management utilities, Excel workbook management, site properties management, Ajax server side utilities, or timer related utilities.
Custom backend extensions
These components are used in the context of any application that references them, and the code is executed in the front-end server where the application is deployed.
They contain the implemented assemblies directly compiled or included through Integration Studio, along with the extension's additional resources.
Whenever you publish an application model (e.g. through Service Studio or when staging an application between environments) the source code of the application is (re)generated, compiled, packaged and deployed.
OutSystems automatically generates and applies a set of differential DDL scripts that are used to updated the database schema based on any changed entities (tables).
This ensures that, at any point, one application model can be consistently generated and deployed to a target environment. It also means that at any point you can revert / rollback to any application version, since all changes are non-destructive and determined based on the current state of the target environment.
The compiler enforces a series of rules and optimizations that ensure applications behave correctly, with native performance, and avoid scalability or reliability issues.
Such rules and optimizations are applied across all layers of the application to ensure the best performance, from database accesses to web page size. Examples include:
- Pages are compressed. To assure that minimal bandwidth is used by applications and that requests made by users are served faster, all pages are automatically compressed to reduce their size.
- Web pages can be partially rendered: By taking advantage of the built-in support for Ajax, the application pages can be partially rendered, thus sending less information to the server and returning only a part of the page. The result is less bandwidth consumption, better responsiveness and an improved user experience.
- Ajax requests are always queued: The generated code assures Ajax requests are always queued so that a given user cannot flood the web application server by sending multiple requests simultaneously to the server.
- Duplicated Ajax requests are dropped: The generated code also assures AJAX requests are only sent once to the Web Application Server, thereby preventing an increase in server load. For example, if several requests from an AutoComplete pattern are queued in the browser, only the last one will be sent to the server.
- Graph analysis sends only the necessary fields to the view state: By using advanced graph algorithms that verify which scope variables are written, read, or not accessed at all, the OutSystems compiler generates code ensuring that only essential fields are sent to the View State, thus highly optimizing the size of the page.
OutSystems enables the modeling of complex business logic without writing code, instead using only simple visual constructs like conditions, cycles, nested calls, assignments, queries, and a wide range of other prepackaged or extended visual building blocks.
These building blocks and services save a lot of work while ensuring that the application is an enterprise-class system. This is because features like transaction handling, auditing, exception handling, Excel file handling, integrated authentication, and user/profile Management are services that are available as visual out-of-the-box elements in OutSystems.
Moreover, a full reference-checking and self-healing engine (TrueChange) assures error-free and consistent changes across all application components. For example, whenever someone modifies a business rule, this engine automatically updates all related business services, data, and user interface elements that use that piece of logic.
Batch processes are throttled
OutSystems allows developers to model business logic that executes asynchronously. Since multiple asynchronous batch processes are possible, these are automatically throttled to ensure that even heavy loads of badly programmed scheduled activities do not take all the processing power required to serve application users.
You can create, model and integrate persistent data repositories based on third-party databases without resorting to traditional complex SQL statements.
OutSystems handles database creation, tuning and integrity with your application during any refactoring operation.
As far as database performance is concerned, the applications are optimized as follows:
- Connections are pooled: This enhances the performance of executing database commands and reduces the amount of time a user must wait for a connection to the database to be established. Connection pooling also avoids the excessive use of operating system, network and database resources that would derive from having one connection per user accessing the application.
- Connections are only kept open if needed: When they are no longer of use, they are automatically released. This allows greater scalability with reduced database resources consumption.
- Transactions are always committed or rolled back and then released: Regardless of what the developer modeled, in the end they are always released - either by committing or rolling back - assuring your application leaves no orphaned transactions or locked tables and does not consume unnecessary resources.
- Queries are only copied to memory if needed: This assures that applications consume the minimum possible amount of memory, despite the fact that they can handle massive data.
- Query fields are only fetched if required: Advanced graph algorithms verify the usage of fields within business logic and user interface so queries exclusively fetch the required fields from the database. This ensures minimal load on the database and minimal data transfer latency, regardless of what the developer coded.
- Queries are contained for duration: If, even with all these optimizations, some queries take too long to execute, OutSystems automatically discards them based on a timeout, to ensure the database is not affected by heavy queries, which enables applications to perform at an optimum level.
- Tables have automated indexing for primary and foreign keys: This optimizes the most common database queries. If more advanced queries require extra indexes in the tables, those can be visually created when your are modeling your data Entities.