What Rainlytics is
Rainlytics is self-hosted web analytics for sites already served by CloudFront. It runs entirely inside one AWS account, and it is built around three constraints.
No third-party analytics JavaScript
Section titled “No third-party analytics JavaScript”Nothing extra is downloaded by the pages being measured. No second DNS lookup, no second connection, no separate script tag. Page weight is most of why this project exists.
An optional beacon covers what server logs cannot see accurately, such as
single-page-app route changes and Core Web Vitals. It is a small TypeScript
module bundled into the site’s existing JavaScript, and it sends a GET to a
path on the site’s own domain. CloudFront logs that request like any other, so
the beacon has no ingestion pipeline of its own.
Full data ownership
Section titled “Full data ownership”CloudFront standard logging writes to your S3 bucket, in Parquet, already partitioned. That bucket is the canonical store, and the data never leaves it. Glue holds the table definitions and Athena reads them in place.
Cost that tracks usage
Section titled “Cost that tracks usage”There is no always-on infrastructure anywhere in the pipeline. Rollups are computed on a schedule by Athena, started by EventBridge Scheduler, and written back as small JSON summaries.
Reading those summaries is what the command line does, so an answer costs a
GET rather than a query. That is the difference between cost tracking your
traffic and cost tracking how often you check your analytics.
The interface is a command line
Section titled “The interface is a command line”rainlytics query runs ad-hoc SQL through Athena, and named subcommands answer
the questions people actually ask.
The reason is authentication. A dashboard needs an identity story, a session model and a way to revoke access, and that subsystem has to stay secure for as long as it exists. A command line on the AWS SDK’s credential chain inherits SSO, MFA, role assumption, least-privilege IAM and CloudTrail audit of who queried what, for no code.
