On Demand App Generation (ODAG) was an approach introduced in Qlik Sense 3.0 to use the Qlik Analytic Platform (QAP) APIs to create Qlik Sense applications for very large or frequently changing data sets.
The ODAG method provides an easy way to generate applications containing slices of data from a very large data set, without needing to load all data into memory in Qlik Sense. Users make selections in "selection" or "parent" apps which contain an aggregated view of the entire data set, and can generate their own apps built using specific scopes of data driven by these selections. The resulting "detail" or "child" apps reload while the user waits to provide up to the full granularity of the data set, over a limited row set.
Qlik Sense 3.0 - via Extension
Initially, functionality was provided via extensions only, interacting with the public APIs. As per the ODAG user guide released with the extension, this required a few tweaks of the Qlik Sense security rules, and upload of the extension (http://branch.qlik.com/#!/project/56f1689bc5b2f734933c7e52) to the server.
As Qlik Sense lacks popular QlikView features like loop and reduce and native document chaining, this provided a first step into making larger data sets accessible with Qlik Sense (without using Direct Discovery, which has limitations).
Qlik Sense June 2017 onward - Native
With the June 2017 release, the extension was moved into Qlik Sense as a native feature, and an on-demand service added to control the logging level and the number of apps that could be generated at one time.
From the extension, the only feature lost was the ability to set a name for the child apps from within the selection app (instead, it takes the name of the template and appends the user directory and name). This gap is partially covered by providing an ODAG "drawer" from which users can recall a list of generated apps, complete with the selections they made to create each one.
Over time, extra configuration options were added, although the initial state allowed developers to specify how many child apps users can keep per ODAG link, and for how long these are retained on the server.
For more information on the configuration options and the code required to create bindings, see this Qlik help page.
Considerations for maximising value from ODAG
Here's a few thoughts on how to reduce risk and increase the stability and scalability of your ODAG solution:
Ensure your aggregated data carries a proxy for the total row count, which can then be used in the ODAG row limit. Aim to keep these slices to ~100,000 rows (depending on your data source and query complexity)
Provide your users with guidance on which fields they need to make selections in and the current row count, and set expectations over generation time and retention of those applications (e.g. if you have an ODAG link set to remove apps after three days, state this in the selection and detail apps)
Provide a summary of selections used to generate the detail app in the detail app. Don't rely on users going back to the selection app and checking the ODAG link pane - ensure you minimise the risk of user error
Ensure the ODAG selection and detail apps have a similar look and feel, as well as navigation. The user should be able to see that the apps are related, and that the detail app is in fact their own copy of a template loaded with only the data they requested
ODAG data sources should be optimised for your queries. For QVDs, this means creating index QVDs which map to the main Fact QVDs via key fields - therefore allowing an optimised load on the slowest step. For technologies like Impala, this is ensuring the table is partitioned by the most common fields a user makes selections in (alternatively, consider using odso to ensure you always limit the data using fields in the partition). In SQL server, Oracle etc, you'll want to be maintaining indexes on important fields and considering the use of integer values or keys
The ODAG binding types (ods/odo/odso) should be used appropriately. Fields with a high number of distinct or long values, should avoid the use of odso (as this passes every selected or optional value in the field), rather using this for date fields that might be indexed in the data source