The short answer
Pick Kimai if you bill clients for your hours: it made a Swedish PDF invoice with 25 % VAT and a total in kronor out of our month of hours, locks last month's hours, stops members from booking past a project's budget, has a team lead role and a Swedish interface, and it ran in about 150 MB. Pick Solidtime for tracking time inside a team that does not invoice from the tracker: it has the more modern interface, an official browser extension and desktop app, and it imports Toggl, Clockify and Harvest exports, but it has no invoices without a paid licence, no Swedish, no approvals or locking, and it needs five containers.
Neither matches the hosted services' approvals out of the box, and neither imported our constructed exports without loose ends.
What we tested
We installed both on the same fresh Melonslab VC-P Alloy (2 vCPU, 8 GB) with Debian 13, each under a user of its own, behind the same Caddy. Kimai followed our guide Track time and invoice with Kimai step by step, and every step worked as written. We have no Solidtime guide, so we ran Solidtime's official image in the same pattern: containers under their own user, Quadlet units, keys and passwords as Podman secrets and our Caddy in front (How we ran Solidtime has the files).
Then we gave both the same data, created through their APIs:
- three customers: Nordljus AB and Bergvik Fastigheter AB, which we bill, and our own company, Exempel AB;
- five projects: Ny webbplats (950 kr an hour, a budget of 150,000 kr) and Support 2026 (850 kr, 40,000 kr) for Nordljus, Hyresgästportal and Driftavtal (1,100 kr each) for Bergvik, and Intern administration, which is not billable;
- the work types Utveckling, Design, Möte, Projektledning, Support and Administration, as activities in Kimai and as tasks per project in Solidtime;
- four people: Anna, the admin; Lars, a team lead; Erik and Sara, members;
- 319 time entries over September 2026, 505 hours in all, 239 entries billable, and some meetings marked not billable.
In a browser, Erik started a timer in each app. We made an invoice or a report for Nordljus for September, locked September in Kimai, imported a small Toggl, Clockify and Harvest export into both, connected Solidtime's browser extension, sent email to a local test mail server, switched to Swedish where we could, rebooted the server, measured memory at rest and in use, and backed up and restored Solidtime.
Toggl Track, Harvest and Clockify were not tested. We did not sign up for any of them. What this page says about them comes from their own pricing and help pages, linked where we use them and read on 14 October 2026.
The numbers
| Kimai 2.69.0 | Solidtime 0.21.0 | |
|---|---|---|
| Containers | 2: Kimai with Apache, MariaDB 11.8 | 5: web app, scheduler, queue worker, PostgreSQL 17, Gotenberg for PDFs |
| Memory at rest after a reboot | about 150 MB (MariaDB 132, Kimai 18) | about 230 MB (web app 140, worker 55, scheduler 26, Gotenberg 8, PostgreSQL 7) |
| Memory at the peak of use | about 172 MB | about 278 MB; about 450 MB while it made a PDF |
| Images on disk | 1.17 GB | 3.33 GB, half of it Gotenberg |
| Data after the test | 193 MB | 53 MB |
From useradd to the login page | about 2 minutes | about 2 minutes 10 seconds |
| Back after a reboot | 69 seconds | 60 seconds |
| Invoices | yes, PDF, with VAT | needs a paid licence |
| Hourly rates and amounts | yes | yes |
| Budgets | money or hours; can block members | estimated hours, shown as progress |
| Locking past hours | yes | no |
| Team lead seeing only their team | yes | no; a manager sees everyone |
| Import from Toggl, Clockify, Harvest | free plugin, Toggl and Clockify | built in, all three |
| Official browser extension, apps | no | browser extension and desktop app |
| Swedish interface | yes | no |
| Licence | AGPL 3.0 | AGPL 3.0 |
Memory is the sum of each app's containers, measured with podman stats five and seven minutes after a reboot; the two readings were within 3 MB. The peak is the highest reading while three requests a second listed, created and summed up time entries through each app's API for three minutes, 540 requests each, none of them failing. Solidtime makes PDFs in Gotenberg, a container with a headless Chromium, which rose from 8 to 191 MB while it made one and stayed at 148 MB afterwards. The setup time is how long the commands took, mostly downloading images, not the time you need to read and type them. Most of Kimai's 193 MB of data is MariaDB's own files.
Setup
Kimai is one container with its own web server and MariaDB in a pod, and our guide worked as written. It took 97 seconds from useradd until Kimai answered, most of it downloading 1.2 GB of images, and about two minutes until we were logged in through Caddy. There is no sign-up page: you create the first account with Kimai's console command, and a short wizard sets language, date format and time zone at the first login.
Solidtime is a Laravel app that runs as three containers from the same image (web app, scheduler and queue worker), with PostgreSQL and Gotenberg next to them. From useradd to the login page took about 2 minutes 10 seconds, most of it downloading 3.3 GB of images. Registration is off by default; the first user is created with a console command, which prints a random password, and the admin panel is for addresses you list in SUPER_ADMINS. Everyone else needs an account, made the same way or in the admin panel, and an email invitation to the organisation, which they accept while logged in. Solidtime's API has no way to add a member without one.
Timers and day-to-day use
Both have a timer in the top bar. In Kimai, Erik pressed the play button, picked a customer, project and activity in a dialog and saved; the button turned into a stop button with the running time. Besides the list of entries, Kimai has a week grid to fill in and a calendar.
In Solidtime, Erik typed what he was working on, picked Ny webbplats from a search list that showed the customer and the project's tasks, and pressed the large play button. Solidtime remembered the half-filled timer when he reloaded the page. Its dashboard shows the week as a chart, recent entries with a button to start them again, and an activity calendar; there is also a calendar view and a timesheet.
Rates, billable hours and budgets
Both took our hourly rates per project in SEK and worked out the same amounts: 173,737.50 kr of billable work for Nordljus in September.
- Kimai keeps rates on a customer, project, activity or user, and the most specific one wins. Each entry is billable or not. A project's page shows its budget used: Support 2026 stood at 138.66 % of its 40,000 kr, with income, costs and profit beside it. With Allow overbooking of stored budgets switched off under System > Settings, Kimai refused Erik's next hour on that project with "Tyvärr, budgeten är förbrukad." ("Sorry, the budget is used up"). Anna, as admin, could still book through the API. Kimai sends no email when a budget runs low; that is a plugin, Budget Watcher, at 99 euros in its store.
- Solidtime keeps rates on the organisation, a project, a project member or a member. Projects and tasks have an estimated time in hours, not money, and the project list shows a progress bar: Support 2026 at 159.6 % of 47 hours, counting non-billable hours too. It does not warn or block. Members in the employee role saw "--" instead of amounts, as we had turned off Employees can see billable rates.
Invoices and the PDF
Kimai made the invoice. Under Invoices we chose Nordljus and September, and Kimai offered 189.75 billable hours, leaving out the non-billable ones, and a total of 217,171.88 kr. The PDF, in Swedish, had our company and Nordljus with addresses and VAT numbers, an invoice number, a due date 30 days ahead, one line per project with hours and hourly rate, as we had chosen in the template, a net amount of 173,737.50 kr, 25 % VAT of 43,434.38 kr, the total, our payment terms and bankgiro number. Saving the invoice marked the hours as exported, so they cannot be billed twice. One catch: the template's Invoice template list has two entries called Invoice. Leave the preselected one, as our guide says; the other makes an HTML file, which we found out by trying it.
Solidtime has no invoices in the free self-hosted version: invoicing is in its paid On-Premise Business licence and in Solidtime Cloud's paid plan. What it does have, for free on your own server, is a PDF report. Our report for Nordljus, billable hours only, showed 189:45 hours and 173,737.50 SEK as a total, a chart per week, and a table per project and task with hours and amounts; the detailed version listed every entry on 8 pages. It has no VAT, no addresses and no invoice number, and its headings are in English, so you write the invoice in your accounting system.
Reports and exports
- Kimai has a Reporting menu with reports per user, per project and per customer, by week, month or year, and Export gives hours as CSV, Excel or PDF. Project pages show hours, budget and profit.
- Solidtime's Reporting has an overview with charts, grouped on two levels such as project and task, and a detailed list, both with filters, rounding and export as PDF, CSV, Excel or ODS. A report can be saved and shared as a public link.
Approvals and locking
Kimai locked the past. Under System > Settings > Lockdown period, we set the period to last month with five days of grace. After that, Erik got "403" when he tried to edit an entry from September, while Anna could still correct it. Weekly approval of timesheets is a free plugin from another developer, which we did not test, and Kimai's own plugin for working hours, holidays and leave, at 299 euros, adds monthly approvals.
Solidtime has neither approvals nor a lock. Anyone with the right to edit an entry can change it, however old it is.
Teams and permissions
- Kimai has roles for user, team lead, admin and system admin, and teams. We put Lars as team lead over Erik and Sara; his team view showed their entries and his own, and none of Anna's. Teams can also limit who sees which customers and projects.
- Solidtime has owner, admin, manager and employee, plus placeholders for people who do not log in, such as those an import brings in. According to its documentation, a manager has full access to projects, clients, time entries and reports for the whole organisation; there are no teams to limit that to.
Import from Toggl, Clockify and Harvest
We did not have accounts at Toggl, Clockify or Harvest, so we wrote a small export from each by hand: four entries for a new customer, Fjällvik AB, two of them by Erik and two by a new person, Nils, one not billable and one with a tag. We used the columns and date formats the two importers document: the Toggl Track and Clockify detailed report, and Harvest's time export as Solidtime reads it. These files were constructed, not exported from the services.
- Solidtime has importers built in, under Import / Export, for Toggl (the time entry export and a full data export), Clockify (time entries and projects), Harvest (time entries, projects and clients) and a generic CSV. All three files imported. From Toggl and Clockify, Solidtime matched Erik by his email address, made Nils a placeholder, created the customer, the projects and the tag, and put the times right in Stockholm time. It did not bring the rates: the new projects were not billable, so the billable entries had no amounts until we set a rate. Harvest's file has names but no email addresses, so Solidtime created placeholders for both people, Erik included, and the entries started at midnight with only their length, as Harvest exports hours, not times.
- Kimai has no importer of its own. Its free Importer plugin, from Kimai's author, reads Toggl Track and Clockify exports, not Harvest. Kimai's store asks for an email address at its checkout; we installed version 2.29.0 from the author's GitHub page instead. Kimai needs an activity for each entry: without a task, the Clockify rows failed with "Empty or missing field" and the Toggl file stopped with an error 500. With tasks filled in, every row that needed a new customer, project or user stopped the import with an error 500. Rows where everything already existed imported, with the amount from the export as the rate. In our versions, you would create customers, projects and users first.
Browser extension and apps
Solidtime has an official browser extension for Chrome and Firefox and a desktop app for Windows, macOS and Linux, both on GitHub. For a server of your own, you create an OAuth client for them with a console command from its Docker guide, and enter your address and the client ID in the extension. We loaded version 0.0.8 of the Chrome extension, signed in as Erik, approved access, and the extension showed his running timer and his entries. We did not test the desktop app. There is no mobile app.
Kimai has no official extension or app. Its integrations page lists apps from other developers, among them Kimai Mobile for iOS and Android from Cloudrizon GmbH at 19.99 euros, which we did not test. Kimai's web interface works in a phone's browser.
We sent email from both to a local test mail server; sending through a real email provider was not tested.
- Kimai sends email for password resets, which our guide covers. Its test command delivered at once.
- Solidtime sent the invitations to Lars, Erik and Sara within seconds, through its queue worker. It also emails anyone whose timer has run for more than 8 hours, and warns before API tokens expire.
API
Both have a REST API with tokens per user, and both took our 319 entries.
- Kimai's API at
/apicovers customers, projects, activities, rates, timesheets, teams and users, with Swagger documentation built in. An admin token creates entries for anyone; our 319 took 25 seconds. - Solidtime's API at
/api/v1covers clients, projects, tasks, members, time entries, reports and imports. You run a console command once before users can create tokens, which are valid for a year. It allows 200 requests a minute, and our script hit that limit, so the 319 entries took about two minutes with retries.
Swedish
Kimai speaks Swedish: the wizard at the first login offers Svenska, with dates as 2026-10-14 and amounts as 1 234,56 kr. A few words are odd: a budget is "Finansplan" and rates are "Avgifter". Solidtime is in English only. It does write numbers, dates and amounts the Swedish way once you set Number format, Date format and the currency SEK in the organisation's settings.
Privacy
Solidtime's scheduler sends usage data by default: on a schedule, your instance's address and the number of users, projects, clients, tasks and time entries go to app.solidtime.io, along with a check for new versions. Two settings in How we ran Solidtime switch both off. Profile pictures without an upload are drawn by ui-avatars.com, which each user's browser fetches. Kimai, as our guide found, makes no outside connections in normal use; only two admin pages contact Kimai's website and GitHub.
Resources
Kimai is a PHP app with Apache. It used 18 MB at rest after the reboot, with only its login page opened, and 38 MB under our three minutes of use; MariaDB held most of the 150 MB. Solidtime keeps three PHP processes running all the time, the web app with FrankenPHP, the scheduler and the queue worker, which make up most of its 230 MB. Gotenberg starts a browser only for PDFs, and keeps about 150 MB after the first one.
Both together used under 400 MB at rest, so either fits a small server, and our 8 GB VC-P Alloy had room for much more.
Updates and backups
Kimai follows the apache tag and updates itself through Podman's auto-update, as our guide sets up. Its backup is a database dump and a volume export, while it runs. Solidtime's files pin the version, 0.21.0, and you update by changing the tag after reading the release notes; with AUTO_DB_MIGRATE the web app updates the database when it starts. Its backup is a dump of PostgreSQL and the storage volume, 0.2 and 2.9 MB in our test. We restored that into empty volumes in 24 seconds, and the 332 entries came back, with the API token still working.
How we ran Solidtime
Solidtime's Docker guide and example files use Docker Compose with five services. We turned those into Quadlet units. Things we learned:
- Each of the three Solidtime containers runs a process manager with a control port on
127.0.0.1:9001, so they cannot share a pod: the second one stops with "Another program is already listening on a port". They share a Podman network instead. - Solidtime's own key command prints the keys with
\nin place of line breaks. We made them withopenssland stored them as Podman secrets. - Solidtime sees Caddy's connections as coming from inside that network, so
TRUSTED_PROXIESnames its subnet, which the network file fixes. Without it, every login showed the container's own address. AUTO_DB_MIGRATE=trueruns database updates when the web app starts, instead of a command after each update.
As a user solidtime, created like kimai in step 1 of the Kimai guide, create the secrets:
printf %s "base64:$(openssl rand -base64 32)" | podman secret create solidtime-app-key -
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:4096 2>/dev/null | podman secret create solidtime-passport-private -
podman secret inspect --showsecret --format '{{.SecretData}}' solidtime-passport-private | openssl pkey -pubout | podman secret create solidtime-passport-public -
openssl rand -hex 24 | tr -d '\n' | podman secret create solidtime-db-password -
printf %s 'your-smtp-password' | podman secret create solidtime-smtp-password -
In ~/.config/containers/systemd, solidtime.network:
[Network]
NetworkName=solidtime
Subnet=10.89.33.0/24
solidtime.env, the settings the three Solidtime containers share, without secrets:
APP_URL=https://solidtime.example.com
APP_ENV=production
APP_DEBUG=false
APP_FORCE_HTTPS=true
TRUSTED_PROXIES=10.89.33.0/24
SUPER_ADMINS=anna@example.com
LOG_CHANNEL=stderr
DB_CONNECTION=pgsql
DB_HOST=solidtime-db
DB_SSLMODE=disable
DB_DATABASE=solidtime
DB_USERNAME=solidtime
QUEUE_CONNECTION=database
GOTENBERG_URL=http://solidtime-gotenberg:3000
MAIL_MAILER=smtp
MAIL_HOST=smtp.example.com
MAIL_PORT=587
MAIL_ENCRYPTION=tls
MAIL_USERNAME=time@example.com
MAIL_FROM_ADDRESS=time@example.com
MAIL_FROM_NAME=solidtime
SCHEDULING_TASK_SELF_HOSTING_TELEMETRY=false
SCHEDULING_TASK_SELF_HOSTING_CHECK_FOR_UPDATE=false
solidtime-db.container:
[Container]
ContainerName=solidtime-db
Image=docker.io/library/postgres:17-alpine
Network=solidtime.network
Volume=solidtime-db:/var/lib/postgresql/data
Environment=POSTGRES_USER=solidtime POSTGRES_DB=solidtime
Secret=solidtime-db-password,type=env,target=POSTGRES_PASSWORD
HealthCmd=pg_isready -U solidtime
HealthInterval=10s
Notify=healthy
AutoUpdate=registry
[Service]
Restart=always
TimeoutStartSec=300
solidtime-gotenberg.container:
[Container]
ContainerName=solidtime-gotenberg
Image=docker.io/gotenberg/gotenberg:8
Network=solidtime.network
AutoUpdate=registry
[Service]
Restart=always
solidtime-app.container:
[Unit]
Requires=solidtime-db.service
Wants=solidtime-gotenberg.service
After=solidtime-db.service solidtime-gotenberg.service
[Container]
ContainerName=solidtime-app
Image=docker.io/solidtime/solidtime:0.21.0
Network=solidtime.network
PublishPort=127.0.0.1:8133:8000
Volume=solidtime-storage:/var/www/html/storage
EnvironmentFile=%h/.config/containers/systemd/solidtime.env
Environment=CONTAINER_MODE=http AUTO_DB_MIGRATE=true
Secret=solidtime-app-key,type=env,target=APP_KEY
Secret=solidtime-passport-private,type=env,target=PASSPORT_PRIVATE_KEY
Secret=solidtime-passport-public,type=env,target=PASSPORT_PUBLIC_KEY
Secret=solidtime-db-password,type=env,target=DB_PASSWORD
Secret=solidtime-smtp-password,type=env,target=MAIL_PASSWORD
[Service]
Restart=always
TimeoutStartSec=300
[Install]
WantedBy=default.target
solidtime-scheduler.container; solidtime-worker.container is the same file with worker for scheduler in the name and this Environment line instead: Environment=CONTAINER_MODE=worker "WORKER_COMMAND=php /var/www/html/artisan queue:work".
[Unit]
Requires=solidtime-app.service
After=solidtime-app.service
[Container]
ContainerName=solidtime-scheduler
Image=docker.io/solidtime/solidtime:0.21.0
Network=solidtime.network
Volume=solidtime-storage:/var/www/html/storage
EnvironmentFile=%h/.config/containers/systemd/solidtime.env
Environment=CONTAINER_MODE=scheduler
Secret=solidtime-app-key,type=env,target=APP_KEY
Secret=solidtime-db-password,type=env,target=DB_PASSWORD
Secret=solidtime-smtp-password,type=env,target=MAIL_PASSWORD
[Service]
Restart=always
[Install]
WantedBy=default.target
Run systemctl --user daemon-reload and systemctl --user start solidtime-app solidtime-scheduler solidtime-worker. It is ready when curl -s -o /dev/null -w '%{http_code}\n' http://127.0.0.1:8133/health-check/up prints 200. Create the first account with the address from SUPER_ADMINS; the command prints its password:
podman exec solidtime-app php artisan admin:user:create "Anna Andersson" anna@example.com --verify-email
For API tokens, run podman exec solidtime-app php artisan passport:client --personal --name=API -n once. The block in Caddy's ~/Caddyfile:
solidtime.example.com {
reverse_proxy 127.0.0.1:8133
}
To back up, run podman exec solidtime-db pg_dump -U solidtime solidtime > solidtime-db.sql and podman volume export solidtime-storage > solidtime-storage.tar, and keep the secrets: the app key and the two passport keys are needed to read what Solidtime has stored. To restore, stop the units, remove the two volumes, create and import solidtime-storage, start solidtime-db, load the dump with podman exec -i solidtime-db psql -U solidtime solidtime < solidtime-db.sql, and start the rest.
Licence and cost
We read the licence texts and pricing pages on 14 October 2026.
- Kimai is made by Kevin Papst in Vienna, Austria, and is open source under the AGPL 3.0, with every feature on this page free except where we name a plugin. Its store sells plugins from Kimai's author and other developers, for example Budget Watcher at 99 euros, expenses at 99 and working hours with holidays and monthly approvals at 299; the Importer and the approval plugin are free. Kimai Cloud, hosted in Germany, costs 2.99 euros per user a month billed yearly (3.99 monthly) for Standard and 3.99 (4.99) for Professional.
- Solidtime is made by solidtime, a partnership in Vienna, Austria, and is open source under the AGPL 3.0. Self-hosted, everything on this page except invoices is free, PDF reports and rates included. Its on-premise pricing lists a Business licence, which adds invoicing and a private image registry, at 199 euros a year for one organisation with five users by default, while the comparison table on the same page says "from €49 / year"; Enterprise has no public price. Solidtime Cloud is free for one user and costs 8 or 9 euros per user a month for Professional.
Toggl Track, Harvest and Clockify today
What follows is from the services' own pages, read on 14 October 2026, not from our tests. Prices are in US dollars per user or seat a month, the lower one billed yearly.
Toggl Track is free for up to 3 users. Starter costs 9 dollars (12 monthly) and adds billable rates and project estimates; Premium costs 16 (24) and adds timesheet approvals, fixed-fee projects and single sign-on; Enterprise has no public price. The page lists alerts for budget and estimate thresholds and exports as PDF, CSV and Excel. According to Toggl's help page, invoices are made from a report as a PDF, with a field for tax; on the Free plan they carry Toggl's logo, and sending them to QuickBooks needs Starter.
Harvest is free for one seat and two projects. Teams costs 9 dollars (11 monthly) and Enterprise 14 (17.50); Enterprise Plus has no public price. Invoicing is in every plan, timesheet approvals and profitability reports in Enterprise. According to Harvest's help center, project managers get an email the morning after a project passes a budget percentage you set.
Clockify has a free plan; its pricing page says up to 5 users in one place and four invited people in another. Basic costs 3.99 dollars (4.99 monthly) with billable rates; Standard 5.49 (6.99) adds invoicing, approval and locking timesheets; Pro 7.99 (9.99) adds budgets, estimates and alerts and a choice of data region; Enterprise 11.99 (14.99) adds single sign-on. According to Clockify's help page, the regions include the EU, hosted in Germany. Toggl's and Harvest's pricing pages do not say where data is stored.
What you give up compared with Toggl, Harvest and Clockify
On your own server the hours and your customers' details stay in Sweden, the cost is the server, not a price per person, and nobody changes the plans under you. But be honest about what you leave behind:
- Apps and integrations. The services come with their own apps and links to other tools, which we did not test. Solidtime has an extension and a desktop app; Kimai relies on apps from other developers.
- The migration. Neither import was clean: Solidtime brought entries but not rates, and turned Harvest's people into placeholders; Kimai's plugin failed on everything new in our versions.
- Approvals and alerts. Harvest and Toggl approve timesheets on their higher plans, and Harvest emails budget alerts. Kimai locks periods and blocks overbooking for free, but approvals and budget emails are plugins; Solidtime has none of these.
- Accounting links. Harvest connects to QuickBooks and Xero, and Toggl sends invoices to QuickBooks. Kimai makes the PDF and leaves the bookkeeping to you; Solidtime leaves the invoice to you.
- Running it. Updates, backups and the server are yours, and you need an email account for invitations and password resets.
Which one to pick
A consultancy that invoices clients by the hour: Kimai. It turns hours into a Swedish PDF invoice with VAT, keeps rates on any level, locks finished months, stops members from booking past a budget, lets team leads see only their team, speaks Swedish and runs in about 150 MB. Its weak points are an older-looking interface, no official app or extension, approvals and budget emails only as plugins, and an importer that failed on new customers and projects in our test. Follow the Kimai guide; a VC-P Alloy runs it with lots of room to spare.
Internal tracking in a team that bills elsewhere, or not at all: Solidtime. It is quick to use, has a browser extension and a desktop app, PDF reports and shareable reports, rates and estimates, and imports from Toggl, Clockify and Harvest. Its weak points are no invoices without a paid licence, no Swedish, no approvals, locking or budget alerts, managers who see the whole organisation, usage data sent by default, five containers and 3.3 GB of images, and no guide of ours yet: the files in How we ran Solidtime are what we ran, on top of the Podman guide. A VC-P Alloy suits it too.
Together they used under 400 MB at rest, so one VC-P Alloy runs both, as ours did.