diff --git a/src/apk_database.h b/src/apk_database.h
index 0539ab84e57bb2b4845ad461bfb78242ba38728f..b1649d18c460b94379bde786837f391bbde90dcd 100644
--- a/src/apk_database.h
+++ b/src/apk_database.h
@@ -154,6 +154,7 @@ struct apk_database {
 	int compat_newfeatures : 1;
 	int compat_notinstallable : 1;
 	int sorted_names : 1;
+	int sorted_installed_packages : 1;
 
 	struct apk_dependency_array *world;
 	struct apk_id_cache *id_cache;
@@ -173,6 +174,7 @@ struct apk_database {
 	} available;
 
 	struct {
+		struct apk_package_array *sorted_packages;
 		struct list_head packages;
 		struct list_head triggers;
 		struct apk_hash dirs;
@@ -254,6 +256,9 @@ int apk_db_install_pkg(struct apk_database *db,
 		       struct apk_package *newpkg,
 		       apk_progress_cb cb, void *cb_ctx);
 
+
+struct apk_package_array *apk_db_sorted_installed_packages(struct apk_database *db);
+
 typedef int (*apk_db_foreach_name_cb)(struct apk_database *db, const char *match, struct apk_name *name, void *ctx);
 
 int apk_db_foreach_matching_name(struct apk_database *db, struct apk_string_array *filter,
diff --git a/src/app_info.c b/src/app_info.c
index fb597d8e29e04abb109a26526a92421d5caf6b69..b7174acf57e4a8ba45cb78105f1e2ed09b268eeb 100644
--- a/src/app_info.c
+++ b/src/app_info.c
@@ -442,7 +442,6 @@ static int info_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *arg
 	struct apk_out *out = &ac->out;
 	struct apk_database *db = ac->db;
 	struct info_ctx *ictx = (struct info_ctx *) ctx;
-	struct apk_installed_package *ipkg;
 
 	verbosity = apk_out_verbosity(out);
 	ictx->db = db;
@@ -455,8 +454,10 @@ static int info_main(void *ctx, struct apk_ctx *ac, struct apk_string_array *arg
 		apk_db_foreach_sorted_providers(db, args, print_name_info, ctx);
 	} else {
 		/* Print all installed packages */
-		list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list)
-			verbose_print_pkg(ipkg->pkg, 1);
+		struct apk_package_array *pkgs = apk_db_sorted_installed_packages(db);
+		struct apk_package **ppkg;
+		foreach_array_item(ppkg, pkgs)
+			verbose_print_pkg(*ppkg, 1);
 	}
 
 	return ictx->errors;
diff --git a/src/database.c b/src/database.c
index bc256836ad900e0cb66d329353dae456e2ab452e..eedbbf0518e6868c4011190a848890975e2a2246 100644
--- a/src/database.c
+++ b/src/database.c
@@ -1266,7 +1266,8 @@ static int write_index_entry(apk_hash_item item, void *ctx)
 static int apk_db_index_write_nr_cache(struct apk_database *db)
 {
 	struct index_write_ctx ctx = { NULL, 0, TRUE };
-	struct apk_installed_package *ipkg;
+	struct apk_package_array *pkgs;
+	struct apk_package **ppkg;
 	struct apk_ostream *os;
 	int r;
 
@@ -1278,8 +1279,9 @@ static int apk_db_index_write_nr_cache(struct apk_database *db)
 	if (IS_ERR(os)) return PTR_ERR(os);
 
 	ctx.os = os;
-	list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
-		struct apk_package *pkg = ipkg->pkg;
+	pkgs = apk_db_sorted_installed_packages(db);
+	foreach_array_item(ppkg, pkgs) {
+		struct apk_package *pkg = *ppkg;
 		if ((pkg->repos == BIT(APK_REPOSITORY_CACHED) ||
 		     (pkg->repos == 0 && !pkg->installed_size))) {
 			r = write_index_entry(pkg, &ctx);
@@ -1667,6 +1669,7 @@ void apk_db_init(struct apk_database *db)
 	apk_dependency_array_init(&db->world);
 	apk_protected_path_array_init(&db->protected_paths);
 	apk_name_array_init(&db->available.sorted_names);
+	apk_package_array_init(&db->installed.sorted_packages);
 	db->permanent = 1;
 	db->root_fd = -1;
 }
@@ -1838,8 +1841,9 @@ static int apk_db_write_layers(struct apk_database *db)
 		int fd;
 		struct apk_ostream *installed, *scripts, *triggers;
 	} layers[APK_DB_LAYER_NUM] = {0};
-	struct apk_installed_package *ipkg;
 	struct apk_ostream *os;
+	struct apk_package **ppkg;
+	struct apk_package_array *pkgs;
 	int i, r, rr = 0;
 
 	for (i = 0; i < APK_DB_LAYER_NUM; i++) {
@@ -1869,12 +1873,14 @@ static int apk_db_write_layers(struct apk_database *db)
 		if (!rr) rr = r;
 	}
 
-	list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list) {
-		struct layer_data *ld = &layers[ipkg->pkg->layer];
+	pkgs = apk_db_sorted_installed_packages(db);
+	foreach_array_item(ppkg, pkgs) {
+		struct apk_package *pkg = *ppkg;
+		struct layer_data *ld = &layers[pkg->layer];
 		if (!ld->fd) continue;
-		apk_db_fdb_write(db, ipkg, ld->installed);
-		apk_db_scriptdb_write(db, ipkg, ld->scripts);
-		apk_db_triggers_write(db, ipkg, ld->triggers);
+		apk_db_fdb_write(db, pkg->ipkg, ld->installed);
+		apk_db_scriptdb_write(db, pkg->ipkg, ld->scripts);
+		apk_db_triggers_write(db, pkg->ipkg, ld->triggers);
 	}
 
 	for (i = 0; i < APK_DB_LAYER_NUM; i++) {
@@ -1962,6 +1968,7 @@ void apk_db_close(struct apk_database *db)
 	apk_dependency_array_free(&db->world);
 
 	apk_name_array_free(&db->available.sorted_names);
+	apk_package_array_free(&db->installed.sorted_packages);
 	apk_hash_free(&db->available.packages);
 	apk_hash_free(&db->available.names);
 	apk_hash_free(&db->installed.files);
@@ -3234,6 +3241,22 @@ static struct apk_name_array *apk_db_sorted_names(struct apk_database *db)
 	return db->available.sorted_names;
 }
 
+struct apk_package_array *apk_db_sorted_installed_packages(struct apk_database *db)
+{
+	struct apk_installed_package *ipkg;
+	int n = 0;
+
+	if (!db->sorted_installed_packages) {
+		db->sorted_installed_packages = 1;
+		apk_package_array_resize(&db->installed.sorted_packages, db->installed.stats.packages);
+		list_for_each_entry(ipkg, &db->installed.packages, installed_pkgs_list)
+			db->installed.sorted_packages->item[n++] = ipkg->pkg;
+		qsort(db->installed.sorted_packages->item, db->installed.sorted_packages->num,
+		      sizeof db->installed.sorted_packages->item[0], cmp_package);
+	}
+	return db->installed.sorted_packages;
+}
+
 int apk_db_foreach_sorted_name(struct apk_database *db, struct apk_string_array *filter,
 			       apk_db_foreach_name_cb cb, void *cb_ctx)
 {
diff --git a/src/package.c b/src/package.c
index 7fe26724db0add2c57c8dd501f3d887acd8eabe0..ca60ccbc854023ab10f47e98712b77a05c1ef3cc 100644
--- a/src/package.c
+++ b/src/package.c
@@ -84,6 +84,7 @@ struct apk_installed_package *apk_pkg_install(struct apk_database *db,
 
 	/* Overlay override information resides in a nameless package */
 	if (pkg->name != NULL) {
+		db->sorted_installed_packages = 0;
 		db->installed.stats.packages++;
 		db->installed.stats.bytes += pkg->installed_size;
 		list_add_tail(&ipkg->installed_pkgs_list,