Open-source project
walinejs/waline avatar
walinejs/waline

Waline: a self-hosted comment system with a serverless backend

đź’¬ A Simple, Safe Comment System

3,123 stars641 forksJavaScriptGPL-2.0

At a glance

What is it?
Waline pairs a lightweight front-end comment widget with a backend you deploy yourself, and it supports PostgreSQL, MySQL, SQLite, TiDB, MongoDB and GitHub as storage. Here is what the repository actually documents, and where the trade-offs sit.
Who is it for?
Waline fits sites that already have a JavaScript front end and want comment data under their own control, especially when a serverless host such as Vercel, Netlify, Railway, Zeabur or CloudBase is already in use. It is a poor fit if you will not maintain a backend at all, or if you need AWS, GCP or Azure deployment today, since the README lists those as unfinished.
Can I use it commercially?
Yes, with conditions. GPL-2.0 is a copyleft licence: if you distribute software that includes it, you must release that software's source code under the same licence. Running it internally without distributing it does not trigger that obligation.
Is it still maintained?
Yes. The repository last received commits 4 days ago.
What is it written in?
Mainly JavaScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 26, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Waline solves, and who it is for

Most comment systems force a choice: a hosted service that owns your data, or a plugin that stores comments inside your site's own database and breaks the moment you regenerate the site. Waline takes a third position. The README describes it as "a simple comment system with backend support", which is the whole design in one line. The comment widget runs in the reader's browser, and a separate backend process you deploy handles storage, spam checks and notifications.

The audience is narrow but clear. Waline targets static sites and documentation sites built with a JavaScript front end, where the author is comfortable deploying a small server or a serverless function. The README lists deployment targets including Vercel, CloudBase, Railway, Render, Zeabur, Netlify, Alibaba Cloud ComputeNest, Docker and plain self hosting. Storage options listed are PostgreSQL, MySQL, SQLite, TiDB, MongoDB, CloudBase and GitHub. That combination is the pitch: you keep the comment data, and you are not locked to one host or one database.

If you run a WordPress site, this is not aimed at you. If you want comments that work with zero backend at all, Waline's own architecture works against you, because the backend is the point.

How the client, server and storage layers fit together

The repository is a pnpm workspace, and the package layout mirrors the three layers. The client lives in packages/client and is published as @waline/client. The server lives in packages/server. There is a packages/admin directory for the management interface, and an example directory holding a deployable sample with its own example/vercel.json and example/package.json. The root package.json exposes scripts named client:build, api:build, admin:build and server:dev, which confirms the split rather than leaving it implied.

Data flow is conventional for this class of tool. The browser loads @waline/client, which renders the comment list and the form and talks to the backend over HTTP. The backend applies the moderation features the README lists: rate limiting by IP, keyword restrictions, an IP disallow list, duplicate content checks, and optional Akismet. It then writes to whichever storage adapter is configured. Notifications go out through email, WeChat, QQ or Telegram, all marked as done in the README's todo list.

The server is also published separately as @waline/vercel, which tells you how the project expects most people to run it: as a serverless function rather than a long-lived process. The README points to a generated OpenAPI document, since the root package.json has an api:lint script that runs redocly lint against packages/server/openapi.yaml. That file is the authoritative description of the HTTP surface, not the README.

Installing Waline and posting a first comment

The README does not give install commands. It points to the documentation at waline.js.org, and the repository carries an example directory and a .env.example for configuration. What follows is drawn from those files, not from a run.

The environment template at the repository root lists the PostgreSQL variables. Note the spelling of the port key as it appears in the file:

bash
POSTGRES_DATABASE=
POSTGRES_USER=
POSTGRES_PASSWORD=
POSTGRES_HOST=
PORSTGRES_PORT=
POSTGRES_PREFIX=
POSTGRES_SSL=

Fill those in for your database, and set POSTGRES_SSL when your provider requires TLS. The example directory has its own example/.env.example, so a deployment based on example/ may expect a separate copy rather than the root file.

For local work, the root package.json defines the scripts you need. The Vercel-flavoured one runs the example app on port 9090:

bash
pnpm install
pnpm server:vercel

The command uses vercel dev against the example directory and listens on 9090, so the backend should answer on that port once the environment variables resolve. For the server package alone, the script is server:dev.

On the page itself, the client is mounted through @waline/client. The documentation gives the mount pattern, which in outline is a script tag loading the client and a call that passes your server URL and a path identifying the current page. The server URL is the deployment you just started; the path is what separates comments on one article from another. If the widget renders but the list stays empty, the usual cause is that the server URL and the page path do not match what the backend recorded.

Where Waline is the wrong tool

The README's own todo list is the most honest limitation. AWS, GCP and Azure deployment support are unchecked, while every other item on that list, from email notification to comment likes, is checked. If your infrastructure lives on one of those three clouds, the documented deployment paths do not cover you, and you would be running the Docker or self-host route instead.

The second constraint is operational. A serverless deployment still needs a database that survives it, and the storage list includes options with very different characters. SQLite in a serverless function is a poor match because the filesystem is not durable across invocations, so the choice of host and the choice of storage are not independent. GitHub as a storage backend is listed, but the README does not describe its write behaviour or rate limits, so anyone considering it should read the documentation rather than assume it behaves like a database.

The third is moderation. Waline ships spam controls, but the README does not claim they are sufficient on their own. Akismet is optional and requires its own key. A site with heavy comment volume will still need a human reading the admin interface, and the repository does not document an escalation path beyond that.

Waline against Disqus and against static-site plugins

The README's topics list includes disqus, which makes the comparison explicit. Disqus is a hosted service: you paste a script, comments live on Disqus infrastructure, and moderation happens in their dashboard. Waline inverts every one of those. You deploy the backend, comments live in your PostgreSQL or MySQL or MongoDB, and moderation happens in the admin package in this repository. The cost of that inversion is real. Disqus works after one line of HTML. Waline needs a deployment, a database and environment variables, and it stops working if you stop paying for the host.

The other comparison is with comment plugins that store data inside the site's own content files. Those keep everything in one repository and need no database, but a rebuild is required for every comment and moderation is editing files by hand. Waline's separate backend exists precisely to avoid that loop, at the price of running a service.

Between the two, the deciding question is not features. It is whether you want a process to operate. Waline's feature list, including social login, sticky comments and article counters, is broad enough that the choice rarely comes down to missing functionality.

Maintenance, upgrades and the GPL-2.0 licence

The repository was last pushed on 2026-09-10, and it is not archived. The root package.json shows a workspace managed with pnpm and a dependency update script, packages:update, that runs npm-check-updates before upgrading every package in the workspace. There is also a packages:check-update script that only reports. That is the documented upgrade path, and it operates on the monorepo rather than on a deployed instance.

For a deployed instance, the upgrade cost depends on how you installed it. A serverless deployment built from @waline/vercel follows that package's releases. A Docker or self-host deployment follows the image or the source. The repository does not document a migration story for database schema changes between versions, and CHANGELOG.md is the file to read before upgrading a live instance.

The licence is GPL-2.0, stated in the README and present as the LICENSE file. GPL-2.0 is a copyleft licence, so if you distribute a modified version of the server, the terms of that licence apply to what you distribute. Running it as a service for your own blog is a different situation from shipping it inside a product. This is not legal advice, and anyone embedding Waline in something they distribute should read the licence text itself.

Editorial conclusion

Waline fits sites that already have a JavaScript front end and want comment data under their own control, especially when a serverless host such as Vercel, Netlify, Railway, Zeabur or CloudBase is already in use. It is a poor fit if you will not maintain a backend at all, or if you need AWS, GCP or Azure deployment today, since the README lists those as unfinished. Before adopting, verify which storage adapter your chosen host supports, check the contents of .env.example against your database, and read the GPL-2.0 licence text against how you plan to distribute anything built on the code.

Frequently asked questions

Which storage backends does Waline support?

The README lists PostgreSQL, MySQL, SQLite, TiDB, MongoDB, CloudBase and GitHub. The root .env.example shows the PostgreSQL variable names, including POSTGRES_DATABASE, POSTGRES_USER, POSTGRES_HOST and POSTGRES_SSL.

Can Waline be deployed on Vercel?

Yes. Vercel is the first entry in the README's deployment table, the server is published as @waline/vercel, and the root package.json has a server:vercel script that runs vercel dev against the example directory on port 9090.

Does Waline support spam filtering and comment moderation?

The README lists IP rate limiting, keyword restrictions, an IP disallow list, duplicate content checks and optional Akismet, plus comment management and deletion. Akismet requires its own configuration, which the README does not spell out.

Official sources

  1. Issues
  2. License: GPL-2.0
  3. Project website
  4. README
  5. walinejs/waline on GitHub
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/walinejs-waline.svg)](https://hysenlabs.com/projects/walinejs-waline)