Developing locally

Last updated:

⚠️ Do not use release-* patterns in your branches unless pushing a release as these branches have special handling related to releases.

Using virtualenv

Note: If you're using the latest generation MacBooks (M1) have a look at this issue for info on how to run PostHog.

If you want to run your development instance using ClickHouse, check out our EE setup section (currently intended for internal use only).

Clone PostHog

  1. Clone the repository:
git clone
  1. Make sure you have Python 3.8 installed python3 --version. pyenv is recommended to manage multiple Python versions and make sure you don't use the system version.

Set up databases

With Docker

  1. Make sure you have Docker and Docker Compose installed and Docker Engine is running
  2. Run:
docker-compose -f up -d redis db

Friendly tip: If you see Error while fetching server API version: 500 Server Error for http+docker://localhost/version: likely Docker Engine isn't running.

Friendly tip: You might need sudo, see more manage docker as non-root.

Without Docker

  1. Make sure you have Redis installed and running. We recommend using version 5 or higher.

    # macOS (Homebrew)
    brew install redis && brew services start redis
  2. Make sure you have PostgreSQL installed and running. We recommend using version 11 or higher. You may also try, but remember to follow the instructions to add psql to your $PATH if you do.

    # macOS (Homebrew)
    brew install postgresql && brew services start postgresql
  3. Create the Postgres database with the command createdb posthog on the shell or by using the Postgres interactive terminal:

    psql -d postgres
    CREATE DATABASE posthog;
    CREATE DATABASE posthog_e2e_test;
    GRANT ALL PRIVILEGES ON DATABASE posthog, posthog_e2e_test TO posthog;
  4. (Optional, if using Homebrew) Create / grant postgres role superuser permissions. Homebrew or installations do not create a superuser named postgres by default, and instead create a superuser with your login username. If you encounter an error like FATAL: role "postgres" does not exist, you may wish to use your login username instead. If that is not possible, create a new superuser by running:

    # macOS (Homebrew)
    # createuser is located in /opt/homebrew/bin/createuser
    createuser --superuser postgres

If you ran brew link postgresql upon installation, there should be no need to specify the full path to createuser.

Running PostHog

  1. Navigate into the correct folder (project's root directory):
cd posthog
  1. Create the virtual environment in current directory called 'env':
python3 -m venv env
  1. Activate the virtual environment:
source env/bin/activate
  1. Install requirements with pip
pip install -r requirements.txt

If you have problems with this step (TLS/SSL error), then run

~ brew update && brew upgrade

followed by

python3 -m pip install --upgrade pip

then retry the requirements.txt install.

Friendly tip: If you're running into errors with this step on a Mac with an Apple Silicon chip, you may need to set some environment variables before running the install command, like so:

CFLAGS="-I /opt/homebrew/opt/openssl/include" LDFLAGS="-L /opt/homebrew/opt/openssl/lib" GRPC_PYTHON_BUILD_SYSTEM_OPENSSL=1 GRPC_PYTHON_BUILD_SYSTEM_ZLIB=1 pip install -r requirements.txt
  1. If you want to fully test all our features, you'll need to install a few dependencies for SAML to run properly. If you're on macOS run the command below, otherwise check out the official xmlsec repo for more details.
brew install libxml2 libxmlsec1 pkg-config
pip install python3-saml==1.12.0
  1. Install dev requirements:
pip install -r requirements-dev.txt
  1. Run migrations:
DEBUG=1 python3 migrate

Friendly tip: The error fe_sendauth: no password supplied connecting to Postgres happens when the database is set up with a password and the user:pass isn't specified in DATABASE_URL. Try export DATABASE_URL=postgres://posthog:posthog@localhost:5432/posthog.

  1. Make sure you have Yarn installed:
# macOS (Homebrew)
brew install yarn
  1. Make sure you have NodeJS installed:
# macOS (Homebrew)
brew install node

Note: For Apple Silicon support, please use NodeJS >= v15.0

  1. Start the backend, worker, and frontend simultaneously with:

Note: The first time you run this command you might get an error that says "layout.html is not defined". Make sure you wait until the frontend is finished compiling and try again.*

Friendly tip: If you run into frontend webpack module errors running rm -rf node_modules/ might help.

Now open http://localhost:8000 to see the app.

To see some data on the frontend, you should go to the http://localhost:8000/demo and play around with it, so you can see some data on dashboard.

Friendly tip: Homebrew services can be stopped with brew services stop <service_name>

Using Docker

Note: Currently Docker does not support Apple Silicon. Please use the virtualenv setup instead.

Note: Developing with Docker may be very slow. If you're planning on doing more than a few simple changes we'd recommend you use the virtualenv setup.

First clone the repository:

git clone

Then start the instance with docker-compose:

docker-compose -f up

It may take several minutes to build the system for the first time. If you see an error message once your app has launched saying the front-end is not built, please wait for the Yarn dependencies to be installed (the logs will output a ✔ Webpack: Compiled successfully message once the frontend is ready).

By default, Docker images include all dependencies for full SAML support. If you want to run your Docker image without these dependencies, please set either SAML_DISABLED=1 environment variable or saml_disabled=1 build argument at build time.

Useful commands

Running backend, worker, and frontend all together

This script runs the below three scripts concurrently, and automatically sets DEBUG=1.

Run ./bin/start

Running backend separately (Django)

Run DEBUG=1 ./bin/start-backend

Running background worker separately (Celery)

Run DEBUG=1 ./bin/start-worker

Running frontend separately (React)

If at any point, you get "command not found: nvm", you need to install nvm, then use that to install node.

Run ./bin/start-frontend

Running backend tests

Run ./bin/tests

To see debug logs (includes e.g. ClickHouse queries), run ./bin/tests --log-cli-level=DEBUG

Running end-to-end Cypress tests

Run ./bin/e2e-test-runner

Debugging the backend in PyCharm

With PyCharm's built in support for Django, it's fairly easy to setup debugging in the backend. This is especially useful when you want to trace and debug a network request made from the client all the way back to the server. You can set breakpoints and step through code to see exactly what the backend is doing with your request.

Configuring the debugger

  1. Setup Django configuration as per JetBrain's docs.
  2. Click Edit Configuration to edit the Django Server configuration you just created.
  3. Point PyCharm to the project root (posthog/) and settings (posthog/posthog/ file.
  4. Add these two environment variables

Let's spin it up!

  1. Run ./bin/start-frontend
  2. Run ./bin/start-worker
  3. Set some breakpoints
  4. In the top toolbar, select the config you just created and click the green bug icon.
  • This runs python runserver with extra parameters that enable debugging.

Testing ingestion and feature flags

Note: When developing locally and setting environment variable DEBUG=1, the local server is treated as what would be "PostHog Cloud". This means that all analytics that are captured from the usage of PostHog are sent to this same local instance (can be quite useful to generate test data too). In addition, feature flags are considered based on the local instance.

Add feature flags to your local instance to use them while developing locally. For example, let's say you want to test the using the my-feature-flag flag locally - you would create a new flag with the name my-feature-flag and release that flag to the user account used for testing. Learn more about using feature flags in the Feature Flags user guide.