Extremely slow performance on Android

Checklist ok :white_check_mark:

Passbolt 5.8.0 and 5.90
Ubuntu server 24.04
Nginx/1.24.0 (Ubuntu)
mysql Ver 8.0.44
PHP 8.3.6

Android-App: 2.6.0
Android-OS: 15 (OnePlus Nord CE 3 Lite 5G) and 16 (NothingPhone 3A)

Hi all,

I’m testing passbolt on a non-docker enviroment, with standard setup on Ubuntu 24.04.

Everything works fine, browser page, plugins, windows app, ios app. Tested directly and also behind NPM proxy.

Only on Android devices (connected on the same lan or via wan, same performance), the login and refresh rate is extremely slow and stuck.

I tried with the Performance Tweaks, but without success.

The problem seems the same of this old post.

Thanks for suggestions.

A.

1 Like

Hello @andspcas

thanks for reaching out. The root cause for slow data refresh from the old post should be resolved by now, se we need to understand more to help. Could you send the Android application log file to help diagnose? (On the authentication screen please click β€œquestion mark” icon - enable logs, then reproduce the slow login and refresh, then click β€œaccess logs” [from app settings or the same β€œquestion mark” icon] and share the file),

Edit: also if login is slow it reminded me of a issue we’ve seen a couple of times.

Thanks

Thanks @mmichalek ,
here the log.

My connection is via local wifi, and the firewal resolves local dns name.

10:34:06 Checking biometry state
10:34:06 Biometry ready
10:34:58 [Session] Passphrase cache cleared
10:34:58 [Session] Passphrase cached
10:34:58 Getting server pgp and rsa keys
10:34:58 β†’ GET https://{passbolt}/auth/verify.json http/1.1
10:34:58 ← 200 OK https://{passbolt}/auth/verify.json (57ms, unknown-length body)
10:34:59 β†’ GET https://{passbolt}/auth/jwt/rsa.json http/1.1
10:34:59 ← 200 OK https://{passbolt}/auth/jwt/rsa.json (56ms, unknown-length body)
10:34:59 Getting server pgp and rsa keys succeeded
10:34:59 Checking if time adjustment is needed
10:34:59 Local time sync needed. Adjusted: 0
10:34:59 Verifying server fingerprint
10:34:59 Server key fingerprint is valid
10:34:59 Preparing sign in challenge
10:35:00 Prepared sign in challenge
10:35:00 Signing in
10:35:01 β†’ POST https://{passbolt}/auth/jwt/login.json http/1.1 (1265-byte body)
10:35:01 ← 200 OK https://{passbolt}/auth/jwt/login.json (153ms, unknown-length body)
10:35:01 Sign in success
10:35:01 Decrypting challenge.
10:35:02 Challenge decrypted successfully
10:35:02 Verifying challenge
10:35:02 Challenge verified with success
10:35:02 Checking MFA status
10:35:02 MFA not required
10:35:02 Authentication success
10:35:02 Increasing sign in count
10:35:04 Fetching feature flags
10:35:04 β†’ GET https://{passbolt}/settings.json http/1.1
10:35:05 ← 200 OK https://{passbolt}/settings.json (50ms, unknown-length body)
10:35:05 Feature flags fetched
10:35:05 RBAC available, fetching RBAC
10:35:05 Password expiry available, fetching expiry settings
10:35:05 Password policies available, fetching password policies settings
10:35:05 V5 metadata available, fetching v5 metadata types and keys settings
10:35:07 β†’ GET https://{passbolt}/metadata/keys/settings.json http/1.1
10:35:07 ← 200 OK https://{passbolt}/metadata/keys/settings.json (44ms, unknown-length body)
10:35:07 β†’ GET https://{passbolt}/rbacs/me.json http/1.1
10:35:07 ← 200 OK https://{passbolt}/rbacs/me.json (37ms, unknown-length body)
10:35:08 β†’ GET https://{passbolt}/password-policies/settings.json http/1.1
10:35:08 ← 200 OK https://{passbolt}/password-policies/settings.json (30ms, unknown-length body)
10:35:09 β†’ GET https://{passbolt}/metadata/types/settings.json http/1.1
10:35:09 ← 200 OK https://{passbolt}/metadata/types/settings.json (31ms, unknown-length body)
10:35:10 β†’ GET https://{passbolt}/password-expiry/settings.json http/1.1
10:35:10 ← 200 OK https://{passbolt}/password-expiry/settings.json (44ms, unknown-length body)
10:35:12 V5 metadata types and keys settings fetched
10:35:12 Fetching user profile
10:35:13 β†’ GET https://{passbolt}/users/me.json http/1.1
10:35:13 ← 200 OK https://{passbolt}/users/me.json (47ms, unknown-length body)
10:35:14 User profile updated successfully
10:35:15 Checking in app review show parameters. Show mode is: ConsecutiveShow. Show interval start date: 2026-01-28. Sign in count is: 6. Should show review: false
10:35:18 [Session] Received authentication intent [Launched]
10:35:18 [Session] Listening for new session events in HomeViewModel
10:35:19 Full data refresh initiated
10:35:20 [Session] Session is valid for request
10:35:20 [Session] Passphrase session is valid for request
10:35:20 [Session] Running operation
10:35:24 β†’ GET https://{passbolt}/metadata/keys.json?contain%5Bmetadata_private_keys%5D=1 http/1.1
10:35:24 ← HTTP FAILED: java.io.IOException: unexpected end of stream on https://{passbolt}/… https://{passbolt}/metadata/keys.json?contain%5Bmetadata_private_keys%5D=1 (1ms)
10:35:24 β†’ GET https://{passbolt}/metadata/keys.json?contain%5Bmetadata_private_keys%5D=1 http/1.1
10:35:24 ← 200 OK https://{passbolt}/metadata/keys.json?contain%5Bmetadata_private_keys%5D=1 (34ms, unknown-length body)
10:35:27 β†’ GET https://{passbolt}/metadata/session-keys.json http/1.1
10:35:27 ← 200 OK https://{passbolt}/metadata/session-keys.json (41ms, unknown-length body)
10:35:27 Building session keys cache; Bundles count: 1
10:35:28 Decrypted session keys bundle
10:35:28 Merging session keys cache
10:35:28 Session keys cache loaded
10:35:29 β†’ GET https://{passbolt}/resource-types.json http/1.1
10:35:29 ← 200 OK https://{passbolt}/resource-types.json (44ms, unknown-length body)
10:35:30 β†’ GET https://{passbolt}/users.json http/1.1
10:35:31 ← 200 OK https://{passbolt}/users.json (47ms, unknown-length body)
10:35:32 β†’ GET https://{passbolt}/groups.json?contain%5Buser%5D=1 http/1.1
10:35:32 ← 200 OK https://{passbolt}/groups.json?contain%5Buser%5D=1 (45ms, unknown-length body)
10:35:35 β†’ GET https://{passbolt}/folders.json?contain%5Bpermission%5D=1&contain%5Bpermissions.group%5D=1 http/1.1
10:35:35 ← 200 OK https://{passbolt}/folders.json?contain%5Bpermission%5D=1&contain%5Bpermissions.group%5D=1 (49ms, unknown-length body)
10:35:40 β†’ GET https://{passbolt}/resources.json?contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&contain%5Bpermissions.group%5D=1&limit=2000&page=1&sort=Resources.modified&direction=desc http/1.1
10:35:40 ← HTTP FAILED: java.io.IOException: unexpected end of stream on https://{passbolt}/… https://{passbolt}/resources.json?contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&contain%5Bpermissions.group%5D=1&limit=2000&page=1&sort=Resources.modified&direction=desc (2ms)
10:35:40 β†’ GET https://{passbolt}/resources.json?contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&contain%5Bpermissions.group%5D=1&limit=2000&page=1&sort=Resources.modified&direction=desc http/1.1
10:35:40 ← 200 OK https://{passbolt}/resources.json?contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&contain%5Bpermissions.group%5D=1&limit=2000&page=1&sort=Resources.modified&direction=desc (39ms, unknown-length body)
10:35:41 Started resource list deserialization
10:35:41 Finished resource list deserialization
10:35:44 Saving session keys cache
10:35:45 Encrypted session keys cache
10:35:45 Skipping session keys update - no local modifications
10:35:52 [Session] Received authentication intent [Disposed]
10:35:52 [Session] Stopping authentication flow in HomeViewModel
10:35:56 [Session] App went background
10:35:56 [Session] Scheduling passphrase cache clear
10:35:56 [Session] Passphrase cache cleared

Thanks for the help

A.

@mmichalek maybe I can do other types of tests?

Thx

A.

I share the same issue, after opening and login into the app it takes a long time before the passwords start to show. I find it rather unusable as a replacement for the default android password manager however never thought of making an issue here.

I experience the following:

  • open the app
  • app asks for password or in my case thinger print
  • after this, it takes time to show the password list but after this it takes a longer time to refresh, i also see after opening an refresh icon and can’t do anything until the refresh is ready

If you need something from my side please let me know

maybe offtopic but it is also a pain in the ass if i need a login name and password, everytime i switch over the app requesting the login details i also need to re-login into the password app.

so app asks login name, i open passbolt
enter my finger print
lookup needed password and login credentials
copy login name and switch over to app
paste login name, after this the app asks password
switch over to passbolt
re-enter my finger print
re-lookup needed password
than i can copy the password

this is to much time and therefore i don’t use it anymore on the mobile devices

my log

Device: OPPO CPH2689
Android 16 (36)
Passbolt 2.6.0-46

10:22:33 [Session] App went background
10:22:33 [Session] Scheduling passphrase cache clear
10:22:33 [Session] Passphrase cache cleared
10:24:33 Checking biometry state
10:24:33 Biometry ready
10:24:39 [Session] Passphrase cache cleared
10:24:39 [Session] Passphrase cached
10:24:43 β†’ POST https://{passbolt}/auth/jwt/refresh.json h2 (105-byte body)
10:24:43 ← 200 https://{passbolt}/auth/jwt/refresh.json (191ms, unknown-length body)
10:24:56 [Session] App went background
10:24:56 [Session] Scheduling passphrase cache clear
10:24:56 [Session] Passphrase cache cleared
10:25:17 Checking biometry state
10:25:17 Biometry ready
10:25:19 [Session] Passphrase cache cleared
10:25:19 [Session] Passphrase cached
10:25:21 β†’ POST https://{passbolt}/auth/jwt/refresh.json h2 (105-byte body)
10:25:21 ← 200 https://{passbolt}/auth/jwt/refresh.json (104ms, unknown-length body)
10:25:59 [Session] App went background
10:25:59 [Session] Scheduling passphrase cache clear
10:25:59 [Session] Passphrase cache cleared
10:28:26 Checking biometry state
10:28:26 Biometry ready
10:28:29 [Session] Passphrase cache cleared
10:28:29 [Session] Passphrase cached
10:28:30 β†’ POST https://{passbolt}/auth/jwt/refresh.json h2 (105-byte body)
10:28:30 ← 200 https://{passbolt}/auth/jwt/refresh.json (113ms, unknown-length body)
10:28:57 [Session] Received authentication intent [Launched]
10:28:57 [Session] Listening for new session events in HomeViewModel
10:29:06 File logging tree planted
10:29:07 Checking biometry state
10:29:07 Biometry ready
10:29:09 [Session] Passphrase cache cleared
10:29:09 [Session] Passphrase cached
10:29:09 Getting server pgp and rsa keys
10:29:10 β†’ GET https://{passbolt}/auth/verify.json h2
10:29:10 ← 200 https://{passbolt}/auth/verify.json (110ms, unknown-length body)
10:29:10 β†’ GET https://{passbolt}/auth/jwt/rsa.json h2
10:29:10 ← 200 https://{passbolt}/auth/jwt/rsa.json (157ms, unknown-length body)
10:29:11 Getting server pgp and rsa keys succeeded
10:29:11 Checking if time adjustment is needed
10:29:11 Local time sync needed. Adjusted: -2
10:29:11 Verifying server fingerprint
10:29:11 Server key fingerprint is valid
10:29:11 Preparing sign in challenge
10:29:11 Prepared sign in challenge
10:29:11 Signing in
10:29:12 β†’ POST https://{passbolt}/auth/jwt/login.json h2 (1681-byte body)
10:29:12 ← 200 https://{passbolt}/auth/jwt/login.json (346ms, unknown-length body)
10:29:12 Sign in success
10:29:12 Decrypting challenge.
10:29:12 Challenge decrypted successfully
10:29:12 Verifying challenge
10:29:12 Challenge verified with success
10:29:12 Checking MFA status
10:29:12 MFA not required
10:29:12 Authentication success
10:29:13 Increasing sign in count
10:29:13 Fetching feature flags
10:29:14 β†’ GET https://{passbolt}/settings.json h2
10:29:14 ← 200 https://{passbolt}/settings.json (90ms, unknown-length body)
10:29:14 Feature flags fetched
10:29:14 RBAC available, fetching RBAC
10:29:14 Password expiry available, fetching expiry settings
10:29:14 Password policies available, fetching password policies settings
10:29:14 V5 metadata available, fetching v5 metadata types and keys settings
10:29:15 β†’ GET https://{passbolt}/rbacs/me.json h2
10:29:15 ← 200 https://{passbolt}/rbacs/me.json (58ms, unknown-length body)
10:29:15 β†’ GET https://{passbolt}/metadata/types/settings.json h2
10:29:15 ← 200 https://{passbolt}/metadata/types/settings.json (98ms, unknown-length body)
10:29:15 β†’ GET https://{passbolt}/password-expiry/settings.json h2
10:29:15 ← 200 https://{passbolt}/password-expiry/settings.json (66ms, unknown-length body)
10:29:15 β†’ GET https://{passbolt}/metadata/keys/settings.json h2
10:29:16 ← 200 https://{passbolt}/metadata/keys/settings.json (112ms, unknown-length body)
10:29:16 β†’ GET https://{passbolt}/password-policies/settings.json h2
10:29:16 ← 200 https://{passbolt}/password-policies/settings.json (75ms, unknown-length body)
10:29:17 V5 metadata types and keys settings fetched
10:29:17 Fetching user profile
10:29:17 β†’ GET https://{passbolt}/users/me.json h2
10:29:17 ← 200 https://{passbolt}/users/me.json (188ms, unknown-length body)
10:29:17 User profile updated successfully
10:29:18 Checking in app review show parameters. Show mode is: ConsecutiveShow. Show interval start date: 2025-08-04. Sign in count is: 7. Should show review: false
10:29:18 [Session] Received authentication intent [Launched]
10:29:18 [Session] Listening for new session events in HomeViewModel
10:29:18 Full data refresh initiated
10:29:18 [Session] Session is valid for request
10:29:18 [Session] Passphrase session is valid for request
10:29:18 [Session] Running operation
10:29:19 β†’ GET https://{passbolt}/metadata/keys.json?contain%5Bmetadata_private_keys%5D=1 h2
10:29:19 ← 200 https://{passbolt}/metadata/keys.json?contain%5Bmetadata_private_keys%5D=1 (65ms, unknown-length body)
10:29:20 β†’ GET https://{passbolt}/metadata/session-keys.json h2
10:29:20 ← 200 https://{passbolt}/metadata/session-keys.json (116ms, unknown-length body)
10:29:20 Building session keys cache; Bundles count: 1
10:29:20 Decrypted session keys bundle
10:29:21 Merging session keys cache
10:29:21 Session keys cache loaded
10:29:21 β†’ GET https://{passbolt}/resource-types.json h2
10:29:21 ← 200 https://{passbolt}/resource-types.json (70ms, unknown-length body)
10:29:22 β†’ GET https://{passbolt}/users.json h2
10:29:22 ← 200 https://{passbolt}/users.json (71ms, unknown-length body)
10:29:22 β†’ GET https://{passbolt}/groups.json?contain%5Buser%5D=1 h2
10:29:22 ← 200 https://{passbolt}/groups.json?contain%5Buser%5D=1 (66ms, unknown-length body)
10:29:23 β†’ GET https://{passbolt}/folders.json?contain%5Bpermission%5D=1&contain%5Bpermissions.group%5D=1 h2
10:29:23 [Session] Received authentication intent [Disposed]
10:29:23 [Session] Stopping authentication flow in HomeViewModel
10:29:23 ← 200 https://{passbolt}/folders.json?contain%5Bpermission%5D=1&contain%5Bpermissions.group%5D=1 (91ms, unknown-length body)
10:29:24 β†’ GET https://{passbolt}/resources.json?contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&contain%5Bpermissions.group%5D=1&limit=2000&page=1&sort=Resources.modified&direction=desc h2
10:29:25 ← 200 https://{passbolt}/resources.json?contain%5Bpermission%5D=1&contain%5Bfavorite%5D=1&contain%5Btag%5D=1&contain%5Bpermissions.group%5D=1&limit=2000&page=1&sort=Resources.modified&direction=desc (454ms, unknown-length body)
10:29:26 Started resource list deserialization
10:29:26 Finished resource list deserialization
10:29:27 Saving session keys cache
10:29:28 Encrypted session keys cache
10:29:28 Skipping session keys update - no local modifications
10:29:31 [Session] App went background
10:29:31 [Session] Scheduling passphrase cache clear
10:29:31 [Session] Passphrase cache cleared

2 Likes

hello @andspcas and @humble-b,

I analyzed and compared the logs and separate threads you mentioned.
First for the logs:
@andspcas:
sign in phase: 20s
refresh phase: 25s

  • there are 2 http failures that are restarted
  • there are some 1-2 seconds gaps between sequential API calls which should not be there - could you investigate why connection is downgrades to http 1.1? (maybe proxy?)

@humble-b:
sign in phase: 9s
refresh phase 10s

  • http 2 used

Sign in phase
The application calls 13 API endpoints (more details here) and for that duration it is blocking as initial configuration and settings for next screens have to be fetched.

Full refresh phase
These are 5 endpoints that fetch all the data (users, groups, folders, resources, resource types), than decrypt them if needed (if changed compared to existing cached version) and insert them into local db for cacheing. Then for next application launch while the refresh indication is still showing the resource list is already loaded and it is possible to navigate through app and resources in read only mode (i.e. can view details but cannot edit) while loading - I see @humble-b you wrote that while the refresh is in progress you cannot use the app - could you explain more?

Biometrics thread
Other thread is authentication screen after each app leave - we have a lot of feedback about that, currently it is in the security model to have this behavior. In this year roadmap we have an item to propose specification and risks for an option for user opt-in in the app settings to change the behavior. Since recent feedback on forum and GitHub, I believe it will gain priority.

iOS comparison thread
Just to comment 2 things about iOS comparison, please notice that the iOS app does not show refreshing indicator, even tough refresh is in progress. That might give feedback that it works instantly after sign-in. Also an average iOS device has better hardware than an Android device - which matters for long resource list, as these are not only networking calls but also CPU-heavy operations (decryption and database i/o). In this cases I see crypto operations were fast, I believe main time build comes from networking.

Saying that, we have a specification for improving performance with still tasks to complete. Some of them were already done (i.e. use pagination in local DB, decrypt and process resources in parallel, skip decryption of unchanged resources) and some of them still to do. Our current focus is on completing the architecture migration (which is more than 80% done) and then we will also tackle performance with the new architecture ready.
Also in terms of time I would say that measurements got by @humble-b are currently expected while @andspcas ones look too high - in my opinion because of networking.

Thanks @mmichalek,
But I have a question.
I performed the installation via the wizard, and after doing some tests, it seems that HTTP 2 is not enabled. Is it possible that there is a difference in the setup of the standard and non-Docker versions?

Thanks.
A.

if you are using TLS the http2 directive is already configured in the nginx configuration from the package: https://gitlab.com/passbolt/passbolt-ops/passbolt-packaging/-/blob/main/debian/conf/nginx-passbolt-ssl.conf#L11

Why do you think it is not enabled?

Hi @max ,
now i tried in this way:

  • new vm clean ubuntu 24.04 LTS
  • created A record and poit to public ip
  • nat 80/443 to vm
  • finish the setup correctly with let’s encrypt challenge
  • terminate the setup correctly
  • access via browser (normally) during setup and post-setup
  • disconnected mobile phone from the wifi and configured access to the app through qr code and through lte connection
  • when logon from mobile the render of the password list (empty) take a long time, and infinite loading icon is showed
  • after 20-30 sec the loading is finished

Maybe its network speed, ok, but:

  • i also tried to point the A record to private ip, connect mobile device to same wifi network, and test but same result

EDIT: in both case in the log i see http 1.1