Skip navigation

Choosing A Mobile App Strategy That’s Right For You

Marshall Levin

Senior Solution Architect, EPAM

When it comes to choosing an approach for your next mobile app, three obvious options come to mind. But there’s a fourth you may want to consider. I’ll explain the pros and cons of each and describe some of the things to consider before going down one of these paths.


Option 1: Native application

This option is pretty obvious. You write one or more versions of your app depending on the platforms you want to support. Objective C or Swift for iOS. Java for Android. .NET for Windows Phone. And so on.

For all but the largest budgets, this is often a non-starter. Sometimes you can achieve a large degree of code reuse using a bytecode-compiled approach like Xamarin that has runtimes for each platform. Sometimes you have a lot of legacy code written in C and you can leverage this by building native libraries and thin platform-specific wrappers. Sometimes you’re building a game and can take advantage of something like Unity, a cross-platform tool that compiles to native code for each platform. But for the most part, multiple platforms mean multiple code-bases in multiple languages, so plan on doubling (or tripling) your development and QA budget, and plan on spending more to find developers with highly specific and highly sought-after skills.

Our clients are most often interested in dynamic, interactive, content-driven applications and want to get their apps to market as quickly as possible. These kinds of apps do not require a high framerate and tend not to leverage very hardware-intensive device functionality. Native application development is generally overkill and represents an unnecessary expense.


Option 2: Responsive web-based app

Another way to go is simply to build a responsive web-based app that can serve your (or your client’s) desktop, tablet and handheld needs. This has some clear advantages. First, you can leverage your existing talent. You most likely already have front-end developers fluent in HTML5, CSS and JavaScript. Of course, there’s more to it than just breakpoints and stacking elements. You need to consider gestures and touches, and most of all you need to consider performance. Users of mobile devices aren’t simply using tiny web browsers. They may have limited bandwidth and inconsistent connectivity, and their mini-computers, powerful as they are, still can’t keep up with a desktop in terms of rendering speed, especially for complex pages, so you will definitely need to keep your pages light and your code clean and efficient.

The biggest downside of this approach, however, is that clients often want a presence in the app stores. While it is possible to create home screen shortcuts to launch your mobile website, there are definite advantages to being in the app store. Your users can rate your app, you can be featured in the app store, and of course you can sell your app easily.

In addition, while HTML5 has made it possible to access many of the device’s hardware features, such as a user’s location or the ability to take pictures with the built-in camera, there are still OS-level features, like push notifications, that require some native code. If you build a responsive web-based app, you won’t be able to provide some of the most compelling functionality that users have come to expect.


Option 3: Cordova/PhoneGap app

Building your mobile app with Apache Cordova, or its Adobe-backed, value-added cousin, PhoneGap, allows you to target multiple mobile platforms with a “true” downloadable, app-store-publishable app that still runs your HTML5-based code.

At its simplest, Cordova provides a thin native application wrapper that simply shows a splash screen and then displays a full-screen “webview” component. You can think of the webview simply as a browser window with no buttons, address bar, or other user controls. It’s simply a stripped-down, bare-bones area for displaying an HTML page.

There’s a bit of a hitch, though. Cordova uses the OS’s built-in webview component to render its HTML5 content. This is, unfortunately, not the same thing as the rendering engine that is part of the Chrome or Safari browser on your mobile device. The webview component tends to lag a few versions behind its full-browser cousin, so just because the latest and greatest HTML5 feature or API is supported by your device’s stand-alone browser doesn’t mean that your Cordova-embedded webview will support it. Check carefully before embarking on a project that depends heavily on an API that could make or break your app.

There are frameworks that help address this issue. Crosswalk, for example, embeds a much more up-to-date rendering engine into your app and is still compatible with Cordova. Some of these solutions are still in their early phases, though, and tend not to have the user base that pure Cordova/PhoneGap have. They are good options if you’re running into issues with unsupported APIs, but if you get stuck, it may be that much harder to find someone else who has the same issue.

In any case, the webview, whichever one you settle on, is simply configured to start up and display a predetermined web page. Typically, this is a local HTML file (i.e., a URL beginning with “file://”). The installed app has your HTML file, along with all of the CSS, JavaScript, images, etc. bundled with it. They’re all just loaded locally. This is no different than loading and viewing an HTML page that is stored on your computer with your favorite browser. There’s no web server involved. You’re simply viewing an HTML page.

Of course, Cordova can do more than just display a web page. It provides, in the form of built-in or third-party plugins, special hooks that allow you, through special JavaScript APIs made available to the webview in which your JavaScript code runs, to access functionality normally only available to you through native code. This is because you are, essentially, running native code. The plugins are platform-specific (although for the most popular ones, there’s almost always both an Android and iOS version). They can do anything that native code can do, but they also expose a few functions to initiate execution and to pass data back and forth between the native realm and the webview realm. For example, you could execute some JavaScript like “cordova.exec(successCallback, failureCallback, “AcmeScannerPlugin”, “scan”)” to tell Cordova to invoke the AcmeScannerPlugin’s “scan” method. The “successCallback” JavaScript function would then receive the result of the scanned barcode. Cordova acts as a mediator and allows you, through its plugin interface, to harness the power of native code. It is also very easy, if you’re proficient with native code, to write your own Cordova plugins.


Option 4: The hybrid-of-hybrids

From the shadows emerges a fourth option, the hybrid-of-hybrids.

Let’s say your client wants to have its cake and eat it, too. Now they want both an installable Cordova/PhoneGap app and a responsive website.

You can certainly achieve a great deal of code reuse with the Cordova/PhoneGap option. You could take the same code running your responsive web-base app and embed a copy of that HTML5 code, probably with minor changes to make it work locally and to leverage Cordova APIs, directly into your Cordova app.

But then you have two copies of your front-end code. What if your back-end changes and you need to make a corresponding change to your front-end code? Well, depending on how you roll it out, you may have two different versions of the front-end (one being served as a web-based version and one baked into your mobile app). They may expect different versions of your back-end services. You would need to push an update to the app store. It may take a while for your app to be approved. Some people may never update the app. You may be stuck supporting legacy versions of your app indefinitely. Sure, you could version your back-end APIs (perhaps something like But this can quickly get pretty hairy. You get the idea.

As you may recall, the Cordova webview simply loads up a URL when it starts. There’s no reason this has to be a local (file://) URL. It could just as easily be an http(s):// URL to fetch a responsive or mobile-optimized web page from your web server. Voilà! We’re done!

Wait, not so fast. This is not a task to be undertaken lightly. There are some serious implications you need to think about, not the least of which are performance and latency. Now, rather than loading a local HTML page, you’re loading a remote resource. Even if your local HTML code eventually loadeddata from a remote resource, at least the basic user interface could start immediately and show some kind of “loading” icon. But if you’re loading even that first resource remotely, your users will have to wait.

There are certainly ways to mitigate this. You could, for example, have a very basic local “bootstrap” HTML page (no, not the framework, but rather the “pull oneself up by one’s bootstraps” concept) that would tell the user to wait while it loaded the remainder of your application, perhaps via AJAX, or perhaps simply by updating the window.location variable. The bootstrap page would not need to rely on any custom API of your back-end, so it would be unlikely to become obsolete and require an update.

However, if you try this approach, you will quickly find a major flaw. If your Cordova-based application is loaded via HTTP and not from the mobile device’s local filesystem, the Cordova-specific JavaScript API is not available to you (at least not in any reliable way, as far as I’ve been able to tell). So while you could serve up a perfectly good HTML5-based application this way, you’d be unable to take advantage of any Cordova plugins and thus any native code.

But there’s still hope. One technique we’ve used successfully relies on the Window.postMessage API.

Create an HTML start page for your Cordova app. This start page will be embedded into the app (Cordova will be loading a file:// URL). On this start page, you’ll create an iframe and set it to 100% width and 100% height. In this iframe, you’ll load your responsive web-based app.

Using JavaScript that executes in the local HTML page (the one that contains the <iframe> tag), you can detect when the iframe content has fully loaded (essentially a “document ready” state). At this point, your local HTML (we’ll call it the “wrapper” page) can target the Window object of the iframe (via its “contentWindow” property) and use the postMessage API to send an data object of your own design to the iframe. This generates a JavaScript event that can be received by code in your iframe.

In your iframe, a receiveMessage function will receive the object from the wrapper page (encapsulated as the “data” property of an “event” object). Congratulations! Your iframe has received a message from the wrapper. It can then make note of the event’s “origin” property (to make sure it is a trusted sender) and the event’s “source” property (to keep a handle to the wrapper’s Window so that the iframe can target the wrapper with a postMessage call of its own).

Ideally, the first message the wrapper sends to the iframe would tell it “hey, lucky you, you’re running inside an iframe within a Cordova wrapper!” From this point forward, we can take advantage of the principles of progressive enhancement. But instead of using techniques like object detection or browser sniffing to determine whether our environment supports some specific functionality, we can simply use the fact that we’ve been notified that we’re running inside Cordova. When our code running inside the iframe would like to take advantage of a feature only available inside Cordova, it can use postMessage to call back to the wrapper. The wrapper, like the iframe code, also has a “receiveMessage” function. The wrapper code, because it is loaded from a file:// URL, has full access to the Cordova API and any native plugins that are bundled with your app. If the iframe asks the wrapper to invoke some native functionality by passing it a message and asking it nicely, the wrapper can invoke the Cordova plugin, get the result, and pass it back, again via postMessage, to the iframe. Your front-end code, which is loaded from your web server, can now do double-duty as your mobile app code, and it doesn’t have any Cordova-specific code getting in the way. It is abstracted thanks to the wrapper page. All your iframe code knows is that a certain feature is available and that Window to which it has a reference is capable of executing said feature when asked via postMessage.

That probably sounded confusing, so here’s some code for you. In your wrapper page, which hosts the iframe, you can do something like this:

// confirm that your iframe content is fully loaded, otherwise there will be nobody listening to receive our message
document.getElementById("myIframe").contentWindow.postMessage({ cordova: true, message: 'yay, you are in Cordova!' }, '');


Now, inside your iframe, you’d do something like this:

window.addEventListener("message", receiveMessage, false);
var wrapperWindow = null;
var isCordova = false;
function receiveMessage(event) {
     // you should probably check event.origin here to see if it is something legit
     wrapperWindow = event.source; // we're going to need this later
     if ( {
      // we are in cordova! yay!
      isCordova = true;


Now, when you want to do something fancy, in your iframe, you’d just do this:

if (isCordova) {
     // yay! we can do something fancy
    wrapperWindow.postMessage({ request: 'fancyFunction' }, '');


Meanwhile, back in wrapper-land:

window.addEventListener("message", receiveMessage, false);
function receiveMessage(event) {
     // you should probably check event.origin here to see if it is something legit
    if ( == 'fancyFunction') {
       // invoke some fancy Cordova function
       // if the result is not returned immediately, the following line would be in the success callback
document.getElementById("myIframe").contentWindow.postMessage({ response: 42 }, '');


And finally back in the iframe, add a clause to your existing receiveMessage function:

if ( {
    alert('the fancy feature says: ' +;

Again, while this approach can allow your HTML5 code to do double-duty and serve both your responsive web-based app as well as your Cordova-based mobile app and thus recognize significant code reuse and eliminate the headaches associated with divergent copies of your front-end code, you’ll still need to address the issues of latency and performance using some of the techniques described above.

Good luck!

Hello. How Can We Help You?

Our Offices

  • Canada

    • Ottawa

      343 Preston Street,
      ON K1S 1N4, Ottawa

    • Toronto

      5 Park Home Avenue,
      Suite 400,
      ON M2N 6L4, North York,

      P: +1-416-591-4004
      F: +1-416-595-1551
  • Mexico

    • Guadalajara

      Periférico Sur #8110,
      Col. El Mante
      45609 Tlaquepaque, Jalisco

      P: +52-33-462-400-98
  • United States

    • Newtown, PA

      41 University Drive,
      Suite 202,
      Newtown, PA 18940

      P: +1-267-759-9000
      F: +1-267-759-8989
    • Bellevue, WA

      110 110th Ave. NE,
      Suite 310
      Bellevue, WA 98004

    • Boston, MA

      21 Drydock Avenue,
      Suite 410 W,
      Boston, MA 02210

    • Conshohocken, PA

      101 East 8th Ave,
      Suite 201,
      Conshohocken, PA 19428

      P: +1-484-382-1300
    • Los Angeles, CA

      11601 Wilshire Blvd,
      Suite 350,
      Los Angeles, CA 90025

    • Mountain View, CA

      465 Fairchild Dr,
      Building B,
      Suite 221,
      Mountain View, CA 94043

    • New York, NY

      24 West 25th Street,
      5th Floor,
      New York, NY 10010

      P: +1-267-759-9000
      F: +1-267-759-8989
    • Philadelphia, PA

      30 South 15th Street,
      9th Floor,
      Philadelphia, PA 19102

    • San Francisco, CA

      222 Kearny Street,
      Suite 308,
      San Francisco, CA 94108

    • Washington D.C.

      7901 Jones Branch Drive,
      Suite 400,
      McLean, VA 22102

  • Austria

    • Vienna

      Nottendorfer Gasse 11,
      1030 Wien

  • Bulgaria

    • Sofia

      69 Bulgaria Blvd.,
      Infinity Tower,
      1404 Sofia

      P: +359-700-20-273
  • Czech Republic

    • Prague

      City Tower building,
      Hvezdova 2b,
      Prague 4
      Czech Republic


      P: +420 22 888 28 23
  • Germany

    • Frankfurt am Main

      Franklinstrasse 56, 
      60486 Frankfurt am Main,

      P: +49-69-31019090
  • Hungary

    • Budapest

      Corvin Offices I.
      Futó street 47-53,
      Budapest, H-1082

      P: +36-1-327-7400
    • Debrecen

      Bethlen Street 3-9,
      Debrecen, 4026

      P: +36-52-999-485 / 45050
    • Szeged

      Felső Tisza-Part 25,
      Szeged, 6723

      P: +36-62-808-013
      F: +36-62-550-655
  • Ireland

    • Dublin

      Alexandra House,
      The Sweepstakes,
      Ballsbridge, Dublin 4,
      D04 C7H2

      P: +353-(0)-1-631-9280
  • Netherlands

    • Delft

      Delftechpark 37j
      2628 XJ Delft

      P: +31 20 241 6134
    • Schiphol

      Evert van de Beekstraat 1, Unit 104,
      1118CL, Schiphol

      P: +31 20 241 6134
  • Poland

    • Gdańsk

      Al. Grunwaldzka 472E
      80-309 Gdańsk

    • Katowice

      Chorzowska Str. 148
      40-101 Katowice

      P: +48-12-222-02-02
    • Krakow

      Opolska Str. 114
      31-323 Kraków

      P: +48-12-222-02-02
    • Warsaw

      ul. Grzybowska 62
      Browary Warszawskie, building J, 9th floor
      00-844 Warszawa

    • Wroclaw

      Ul. Piotra Skargi 1,
      Budynek A,
      50-082 Wrocław

  • Spain

    • Malaga

      Av. Imperio Argentina, 19-21,
      2º Planta,
      29004 Málaga,

  • Sweden

    • Göteborg

      Lilla Nygatan 2,
      411-09 Göteborg

      P: +46-85-250-06-98
    • Stockholm

      Kungsgatan 50,
      111 35, Stockholm

      P: +46-85-250-06-98
  • Switzerland

    • Glattpark

      Boulevard Lilienthal 2,
      8152 Glattpark (Opfikon)

      P: +41-43-500-21-49
  • Ukraine

    • Dnipro

      17A Volodymyra Monomaha Street,
      49000 Dnipro

      P: +380-56-790-5651
    • Kharkiv

      33G 23 Serpnya Street,
      61072 Kharkiv

      P: +380-57-728-06-22
    • Kyiv: Registered office

      28 Fizkultury Street,
      03150 Kyiv

      P: +380-44-390-5457
      F: +380-44-390-0861
    • Kyiv: Visitors office

      14B Kudryashova Street,
      03035 Kyiv

      P: +380-44-390-5457
    • Lviv

      45 O.Stepanivny Street,
      79018 Lviv

      P: +380-32-242-4642
      F: +380-44-390-5458
    • Vinnytsia

      51 Ovodova Street,
      21000 Vinnytsia

      P: +380-432-551-294 +380-432-551-275
      F: +380-432-551-293
  • United Kingdom

    • London

      114 Middlesex Street,
      London, E1 7HY
      United Kingdom

      P: +44-203-514-0027
    • Manchester

      Tower 12,
      18-22 Bridge Street,
      Manchester, M3 3BZ
      United Kingdom

      P: +44-203-514-0027
  • Australia

    • Sydney

      Level 19, 68 Pitt Street,
      Sydney, NSW, 2000,

      P: +61-28-310-82-72
  • China

    • Guangzhou

      Unit B01, 23/F,
      Yuexiuxinduhui Building,
      No. 236, 6th Zhongshan Road,
      Yuexiu District, Guangzhou,
      China 510180

    • 广州

      越秀新都会大厦中座 23楼 B01室

    • Shanghai

      Room B509, 5th Floor,
      48 Weihai Road,
      Huangpu District, Shanghai,
      China 200000

      P: +86-21-53080606
    • 上海


      P: +86-21-53080606
    • Shenzhen

      3/F, Block 5, Vision Shenzhen Business Park,
      9th Gaoxin South Road, 
      Shenzhen Hi-tech Industrial Park,
      Nanshan District, Shenzhen,
      Guangdong, China 518057

      P: +86-755-36899008
    • 深圳


      P: +86-755-36899008
    • Suzhou

      Building 12, Creative Industrial Park,
      328 Xinghu Street,
      Suzhou Industrial Park,
      Suzhou, China 215123

    • 苏州


  • Hong Kong

    • Hong Kong

      198 Wellington Street,
      17F, Central
      Hong Kong

      P: +852-5808-6018
  • India

    • Bangalore

      Global Technology Park,
      Block C, Outer Ring Rd,
      Adarsh Palm Retreat, Bellandur,
      Bengaluru, Karnataka 560103

    • Hyderabad

      10, 11 & 12th Floors,
      Salarpuria Sattva Knowledge City,
      Plot No. 2, Phase - 1,
      Survey No. 83/1,
      Raidurgam Village,
      Serilingampally Mandal,
      Hyderabad, Telangana - 500081

      P: +91-40-47979900
    • Pune

      SmartWork Business Center Pvt Ltd,
      Suite 8, Level 1,
      West Wing, Nyati Unitree,
      Samrat Ashok Road,
      Yerwada, Pune - 411006,

      P: +91-20-4913-6025
  • Japan

    • Tokyo

      Floor 1-10-11
      Shibadaimon Centre Building 10th
      Shibadaimon Minato-ku
      Tokyo 105-0012

      P: +81-03-6880-9198
      F: +81-03-6880-9201
  • Singapore

    • Singapore

      5 Shenton Way
      UIC Building, #10-01,
      Singapore (068808)

      P: +65-6911-6888
  • United Arab Emirates

    • Dubai

      EPAM Systems FZ-LLC Dubai Branch
      2307 Arenco Tower, Dubai Media City
      PO Box 501929 Dubai
      United Arab Emirates

      P: +971-4-568-3569
  • Armenia

    • Yerevan

      15 Khorenatsi Street,
      Elite Plaza Business Center,
      0010 Yerevan

      P: +374-10-60-00-65
  • Belarus

    • Brest

      6A Masherov Avenue,
      224030 Brest

      P: +375-162-52-5268
      F: +375-162-50-9888
    • Gomel

      80 Rechitsky Avenue,
      246012 Gomel

      P: +375-17-389-0100, ext. 54079
      F: +375-232-70-50-31
    • Grodno

      87B Gorkogo Street,
      230005 Grodno

      P: +375-17-389-0100, ext. 69011
    • Minsk

      1/1 Academician Kuprevich Street,
      Suite 110,
      220141 Minsk

      P: +375-17-389-0100
      F: +375-17-268-6699
    • Mogilev

      19 Cosmonaut Street,
      Suite 510,
      212009 Mogilev

      P: +375-17-389-0100, ext. 1001
    • Vitebsk

      11-a Stroitelei Avenue,
      Suite 311,
      210032 Vitebsk

      P: +375-17-389-0100, ext. 54433
  • Kazakhstan

    • Astana

      8 Auezova Street,
      Office B,
      010000 Astana

      P: +7-7172-475-970
      F: +7-7172-688-774
    • Karaganda

      58/3 Ermekova Street,
      100009 Karaganda

      P: +7-7212-93-01-01 +7-7212-93-01-00
  • Russia

    • Moscow

      9th Radialnaya Street,
      Building 2,
      115404 Moscow

      P: +7-495-730-6362
      F: +7-495-730-6361
    • Izhevsk

      150 V. Sivkova Street,
      426000 Izhevsk

      P: +7-3412-27-13-37
    • Nizhny Novgorod

      30 Poltavskaya Street
      603089 Nizhny Novgorod

    • Ryazan

      16 Gogolya Street,
      390035 Ryazan

      P: +7-4912-55-99-10
    • Saint Petersburg

      22/2 Zastavskaya Street,
      196084 Saint Petersburg

      P: +7-812-611-1094
      F: +7-812-611-1094
    • Samara

      21 Michurina Street,
      443110 Samara

      P: +7-846-200-0970
    • Saratov

      37 Tankistov Street,
      410019 Saratov

      P: +7-8452-692-981
    • Sergiev Posad

      7 Akademika Silina Street,
      141313 Sergiev Posad

      P: +7-496-547-11-39
      F: +7-496-547-11-39
    • Togliatti

      31E Yubileynaya Street,
      445037 Togliatti

      P: +7-495-730-6360, ext. 47650
    • Tver

      8 Kolodkina Street,
      170002 Tver

      P: +7-4822-630-070 +7-4822-630-071 +7-4822-630-072
      F: +7-4822-630-073