Upgrading YAFFA
Most updates of YAFFA only require the usual steps for your hosting option. Major versions can contain breaking changes, so read the section of the version you upgrade to before you start.
This page summarizes the most important points. The complete, detailed upgrade notes are maintained together with the application in the UPGRADE.md file of the YAFFA repository, which also covers the upgrades from older versions.
The usual update steps
- Docker: pull the new image and restart the containers. The container takes care of running the migrations, clearing the caches, and rebuilding the assets on startup.
- Source code / Composer: pull the new code, install the dependencies, run the migrations, clear the caches, and rebuild the assets. See the commands below.
Always create a backup of your database before a major upgrade.
Upgrade from YAFFA 3.x to 4.x
YAFFA 4.0 changes how budgets work, and includes some infrastructure changes. The database migration converts your existing data automatically, but some of the changes cannot be reversed, so a backup is your only way back to 3.x. Rolling the migration back restores the structure of the tables, but not your data.
What changes
Budgets are standalone
- A budget is now a category-level spending or income target, with no fake transaction behind it. It can apply to the category in general, or to one specific account.
- The "Budget" checkbox of the transaction form is gone. Categorized items of a scheduled withdrawal or deposit now always count toward the budget comparison. There is no replacement setting to opt in or out.
- You create, edit, and delete budgets in Reports → Schedules and Budgets, next to your schedules.
- Existing budget-only transactions are converted into budgets automatically (one per category), and the original transactions are permanently deleted.
- Schedules and budgets support more flexible recurrence (such as the first Wednesday of the month, or the last business day of the month), and an optional annual inflation rate. The way recurrence is stored changed internally, but the settings you see are the same.
Other changes to be aware of
- reCAPTCHA is removed from the login, registration, and password reset forms. The
RECAPTCHA_SITE_KEYandRECAPTCHA_SECRET_KEYsettings are not used anymore, and you can delete them from your.envfile. If your instance is public, note that this bot protection is gone. Login attempts are still rate limited, and users can now turn on two-factor authentication. - New optional security features: two-factor authentication and personal API tokens. Neither is enabled by default. The abilities of API tokens are enforced on every endpoint, and the API rate limit is 120 requests per minute for each user.
- The BCMath PHP extension is required. Docker users have it. If you run PHP yourself, check with
php -m | grep bcmathbefore upgrading. See the technology stack. - Exact decimal arithmetic replaces floating point calculations for money and quantities. In the API, several amount, price, and quantity fields are now returned as decimal strings instead of numbers (see API access). This matters only if you have custom scripts.
- AI documents: deleting an AI document does not delete the transaction created from it anymore. There is also a new, optional retention setting for automatic cleanup.
- Investment transactions recorded before a currency change: if the currency of an account or an investment was changed after a transaction was recorded, the cash flow value of that transaction cannot be calculated anymore, and a warning is logged ("Investment transaction cash flow spans mismatched currencies (legacy data)"). Search your logs for it after the upgrade, and correct the transactions listed.
- Web scraping of investment prices was reimplemented with a different HTTP client and HTML parser. It should work the same way, but check the retrieval status of your scraped investments after the upgrade.
- If you have custom scripts or integrations using the API, review them before upgrading. Among other changes, the
typeparameter of the scheduled items endpoint does not acceptbudget,budget_only,both, andanyanymore, and there are new endpoints for budgets.
Step by step
1. Upgrade to the latest 3.x release
First update to the latest YAFFA 3.x release (3.6.0 or later). This makes sure that the safety check command of the next step is available.
2. Run the safety check (optional, but recommended)
Run the following command on your current 3.x installation. It is read-only.
php artisan app:check:budget-migration
It reports the budget-only transactions that cannot be converted safely, such as one without any items, one where the only account is a payee, a transfer or investment transaction with a budget flag, or one whose currency does not match its account. The 4.x migration refuses to run while any of these exist, so fix the reported transactions (edit or delete them), and run the command again until it finishes without issues. With Docker, run it inside the application container, for example docker compose exec app php artisan app:check:budget-migration.
3. Back up your database
Create a complete backup before you upgrade, and keep it until you are sure that everything works. For Docker, see the backup guide. Without Docker, for example:
mysqldump -u username -p database_name > yaffa_backup_$(date +%Y%m%d).sql
4. Review your .env file
No new setting is required, but the new version of the framework (Laravel 13) builds the default names of the cache prefix, the Redis prefix, and the session cookie differently. If your .env file does not set these explicitly, add the following lines to keep your existing cache, queue, and session data. If you changed the name of your application, replace yaffa with the slug of that name.
CACHE_PREFIX=yaffa_cache_
REDIS_PREFIX=yaffa_database_
SESSION_COOKIE=yaffa_session
Also delete the RECAPTCHA_* settings, which are not used anymore.
5. Install the new version
Docker
docker compose pull
docker compose stop app scheduler
docker compose up -d db
docker compose up -d app scheduler
The container runs the migrations on startup. Only the app container does this, and the scheduler container waits for it.
A few Docker-related changes to know about:
- You don't need to set
APP_KEYanymore. If it is empty, the container generates a key on first start and keeps it in the storage volume. If you already have a key in your.envfile or Compose environment, it is still used. Don't delete the storage volume without a copy of the key. - Caddy is a Compose profile now. Instead of uncommenting the Caddy block of the
docker-compose.ymlfile, you start it withdocker compose --profile https up -d. If you edited the old block by hand, pulling the new file conflicts with your edit or discards it, so download the new file, and apply your domain and Caddyfile settings again. Also setAPP_PORTin your.envfile (for exampleAPP_PORT=127.0.0.1:8080), so theappservice does not try to use port 80 next to Caddy. See the installation guide.
Source code / Composer
git pull
composer install
php artisan migrate
php artisan config:clear
php artisan cache:clear
php artisan view:clear
npm install && npm run build
The migration converts your schedules and budgets, removes the old budget flag, and adds some missing indexes and unique keys. Before adding the unique keys, duplicated tag assignments and duplicated payee category preferences are removed automatically. These only inflated counts or repeated a preference, so no manual step is needed.
6. Review your converted budgets
Open Reports → Schedules and Budgets, and filter the list to budgets to review what was converted from your old budget-only transactions. A converted budget is tied to an account only if the original transaction had a real account, otherwise it applies to the category in general. No further action is needed, unless you want to adjust the targets.