Speeding up APEX Static Application and Workspace Files

A few years ago it was deemed state-of-the-art to store any kind of extra resources (images, css/js-files) directly on the webserver.

Of course this was just the best-practice, left with many who were not able to follow because of company restrictions: no access to web server, not allowed to store files, too many regulations, and so on.

Luckily APEX 5++ gave us nicely working Static Application Files and Static Workspace Files. Now everyone is using those to store extra files.

But there is a downside: it is still a hit on the database retrieving a BLOB.

This doesn’t really matter, if there is just a few consistent users, but has a huge impact for many first time visitors as on public websites like fab.earth, apex.oracle.com, or builtwithapex.com.

If you think this doesn’t concern you: APEX Theme Styles and Plugin Files are loaded the same way and benefit also from a speedup.

There is a very simple way to speed things up, which also works for any ORDS webservice you might use to deliver rather static content (ie.hardly ever changing images, …).

Anyway, here we go: the solution to speed up serving dynamic content is to cache it on the webserver.

If you have read my post on the Oracle APEX Reverse Proxy Guide using nginx, you already figured I like to use nginx, a free and lightweight alternative to Apache.

At first we need to know how APEX static files work: they are served through an ORDS webservice called “r”. For example https://myhost.prost/ords/myworkspace/r/files/static/v2/testimage.png

What we can see in this file-path is the folder /r/, which in fact is a generic ORDS webservice used for all kinds of APEX files (application, workspace, theme-style, plugin, …). But there is also a version number (v2) as part of the path. Whenever we change the file (update the image, …) the version number changes.

This is great information, because it means a full file path always results in the very same file. New file, new path.

So instead of passing the same file path over and over again to ORDS to read that file from the database, we can tell the webserver to cache a copy of that file and serve it directly to the next request.

In nginx-configuration we can easily set up a cache like this:

1. configure a cache bucket2. tell nginx which file-path to cache

The explanation for all those settings is documented in the official documentation. In short: put every file found on a path like /ords/*/r/*files/static/vnnn/ subfolder for at least 24hrs and also send a 300 day expiry header to the client.

For www.builtwithapex.com we also serve images (screenshots of websites) through an ORDS webservices, which is cached in a similar manner. That helped us to speed up file access by more than 300%.

That’s what I call an easy and quick win !

Edit 24.04.2020
The path to determine if it is a static application or workspace file was refined to avoid false positives with APEX 20.1 friendly url.

4 thoughts on “Speeding up APEX Static Application and Workspace Files

  1. Thanks Peter, great work!
    a silly question, could you please share the code allowing non-static files to pass to ORDS?

    as soon as I added something like this
    location ^~ /ords/ {proxy_pass http://10.0.0.2:8080/ords/;}

    X-Cache-Status is no longer set.

    Thanks
    Frank

  2. Hi Peter,
    Thanks a lot for your post. I’m following your indications and I just have 2 comments:
    1) Could you please post the text so I can copy/paste the config? I’ve copied it manually but I’m not confident to have any typo.
    2) Is there any way to actually check that the cache is active? (I mean with Chrome dev tools or something similar) I’ve checked content of directory /var/lib/nginx/cache and it’s empty in the server.

    Thanks a lot!

  3. Jose,
    here is the copied text:

    # cache apex application/workspace static files
    location ~* /ords/(.*)/r/([0-9/]*)files/static/v([0-9]+)/ {
    proxy_cache backcache;
    proxy_cache_key $host$uri$is_args$args;
    proxy_cache_valid 200 24h;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_pass http://127.0.0.1:8080;
    proxy_redirect off;
    add_header X-Cache-Status $upstream_cache_status;
    expires 300d;
    }

    In developer-tools check the response headers x-cache-status (if configured on your webserver).

  4. … because as per your comments, (this is my Chomre devtools output), it seems the cache is not activated…
    GENERAL:
    Request URL: http://xxxxxx.josearostegui.com:8080/ords/heroapps/r/500/files/static/v88/hero-logo.png
    Request Method: GET
    Status Code: 200
    Remote Address: 212.227.205.227:8080
    Referrer Policy: strict-origin-when-cross-origin

    RESPONSE HEADERS:
    HTTP/1.1 200
    Content-Disposition: inline; filename=”hero-logo.png”; filename*=UTF-8”hero-logo.png
    X-Frame-Options: SAMEORIGIN
    Content-Type: image/png;charset=utf-8
    Transfer-Encoding: chunked
    Date: Mon, 21 Dec 2020 13:19:10 GMT

Leave a Reply

Your email address will not be published. Required fields are marked *