Realize the potential of the cloud with Aptaria.

Tuesday, July 22, 2008

Considerations when programming in a multi-tenant environment

Developing enterprise applications in a multi-tenant environment introduces additional considerations for the developer. All well designed On-Demand platforms (known as Platform-as-a-Service or PaaS) must automatically subject all resident applications to additional constraints not often found in on-premise platforms such as .Net or Jave EE. These additional checks ensure that all applications that are sharing common infrastructure are well-behaved and don't hog resources or otherwise adversely affect their fellow tenants co-located on the platform. Note that many of these constraints are enforced at run-time when the platform ungracefully terminates your offending query.

As just one example consider Salesforce's force.com platform and its Apex programming language. The force.com platform closely controls the execution of Apex with embeded SOQL statements (the platform's custom varient on SQL). Care must be taken to prevent a runaway query from hogging resources and slowing down everyone's execution time. This is especially of concern to those larger enterprises with more than 100,000 rows of data in one force.com object (table) because SOQL queries that hit such tables are more likely to be flagged for termination by the platform.
select id from asset where Parent_Asset__c = :a.id
where asset is an object associating Accounts with the Product2 to identify which products a customer has purchased and Parent_Asset__c identifies the id of corresponding asset on the Parent account.

This query appears innocent enough, and on most salesforce.com orgs, it would execute without a problem. But when it is executed against a table with more than 100,000 rows, the platform terminates this query with the following error message to protect the integrity of the platform:

System.QueryException: Non-selective query against large object type (more than 100000 rows). Consider an indexed filter or contact salesforce.com about custom indexing. Even if a field is indexed a filter might still not be selective when: 1. The filter value includes null (for instance binding with a list that contains null) 2. Data skew exists whereby the number of matching rows is very large (for instance, filtering for a particular foreign key value that occurs many times)

Medium and large enterprises can quickly accumulate multiple objects (tables) with significantly more than 100,000 rows. Clearly a different approach is needed for SOQL queries against any table that could potentially have more than 100K rows.
The solution for this client is to add additional constraints to the SOQL where clause as follows:
select id from asset where accountid = :childAccs.id and Parent_Asset__c = :a.id
This updated SOQL statement passes the additional force.com run-time checks and executes without incident.

Custom development on a Platform-as-a-Service brings with it additional considerations that must be handled properly to avoid nasty run-time errors. This is especially true for larger enterprises with large amounts of data (100K rows in the case of force.com).
With care, custom Apex applications can be developed in a way that meets the needs of the users without compromising the integrity of the multi-tenant platform on which it runs.