Skip to content

feat(experimentation): add per-organisation ingestion infrastructure service#8035

Merged
gagantrivedi merged 7 commits into
mainfrom
feat/experimentation-analytics-infra-service
Jul 21, 2026
Merged

feat(experimentation): add per-organisation ingestion infrastructure service#8035
gagantrivedi merged 7 commits into
mainfrom
feat/experimentation-analytics-infra-service

Conversation

@gagantrivedi

Copy link
Copy Markdown
Member

Thanks for submitting a PR! Please check the boxes below:

  • I have read the Contributing Guide.
  • I have added information to docs/ if required so people know about the feature.
  • I have filled in the "Changes" section below.
  • I have filled in the "How did you test this code" section below.

Changes

Adds a service layer for provisioning per-organisation experiment events ingestion infrastructure, to be consumed by the events ingestion server and hooked up to an API later.

  • New experimentation/ingestion_infra_service.py: provision_ingestion_infrastructure(organisation_id) idempotently creates an S3 events bucket and a DirectPut Firehose delivery stream per organisation.
  • The stream uses dynamic partitioning on each record's environment_key, so objects land under per-environment S3 namespaces (events/env_key=.../year=.../...) and are batched per environment.
  • New settings: INGESTION_EVENTS_BUCKET_PREFIX, INGESTION_FIREHOSE_DELIVERY_ROLE_ARN (a single shared Firehose delivery role, provisioned out-of-band, scoped by bucket naming convention).

Note: with a shared delivery role, per-stream/bucket isolation is enforced by the control plane (only this service sets stream destinations), not IAM; per-organisation roles are a possible v2 hardening.

How did you test this code?

Unit tests with moto covering fresh provisioning (full destination config), idempotent re-runs, missing-settings errors, and AWS client error propagation. make lint, make typecheck, and the full experimentation unit suite pass locally.

@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

3 Skipped Deployments
Project Deployment Actions Updated (UTC)
docs Ignored Ignored Preview Jul 21, 2026 5:43am
flagsmith-frontend-preview Ignored Ignored Preview Jul 21, 2026 5:43am
flagsmith-frontend-staging Ignored Ignored Preview Jul 21, 2026 5:43am

Request Review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 44bee4e4-95a6-4250-ae8f-a83d8b086775

📥 Commits

Reviewing files that changed from the base of the PR and between 51d767f and e2124c3.

📒 Files selected for processing (1)
  • api/experimentation/ingestion_infra_service.py
💤 Files with no reviewable changes (1)
  • api/experimentation/ingestion_infra_service.py

📝 Walkthrough

Walkthrough

Adds an environment setting and immutable return type for ingestion infrastructure. Implements organisation-scoped S3 bucket and AWS Firehose delivery stream provisioning, including lifecycle, access, partitioning, compression, and error-output configuration. Updates production and staging task definitions with the delivery-role ARN, documents creation events, and adds mocked AWS tests covering validation, configuration, headers, logging, and error propagation.

Estimated code review effort: 4 (Complex) | ~45 minutes


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added api Issue related to the REST API docs Documentation updates feature New feature or request and removed docs Documentation updates labels Jul 17, 2026
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.65%. Comparing base (0838195) to head (e2124c3).
⚠️ Report is 5 commits behind head on main.

Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8035      +/-   ##
==========================================
+ Coverage   98.64%   98.65%   +0.01%     
==========================================
  Files        1506     1514       +8     
  Lines       59573    60110     +537     
==========================================
+ Hits        58767    59304     +537     
  Misses        806      806              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added the docs Documentation updates label Jul 20, 2026
@gagantrivedi
gagantrivedi force-pushed the feat/experimentation-analytics-infra-service branch from e75bdc5 to ab5cb97 Compare July 20, 2026 09:25
@github-actions github-actions Bot added feature New feature or request docs Documentation updates infrastructure and removed feature New feature or request docs Documentation updates infrastructure labels Jul 20, 2026
@gagantrivedi
gagantrivedi marked this pull request as ready for review July 20, 2026 10:46
@gagantrivedi
gagantrivedi requested review from a team as code owners July 20, 2026 10:46
@gagantrivedi
gagantrivedi requested review from germangarces and khvn26 and removed request for a team July 20, 2026 10:46
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request labels Jul 20, 2026
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request infrastructure docs Documentation updates labels Jul 20, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
api/experimentation/ingestion_infra_service.py (1)

195-200: 🩺 Stability & Availability | 🔴 Critical | 🏗️ Heavy lift

Handle partial provisioning failures to avoid permanently breaking retries.

Because _create_events_bucket and _create_delivery_stream unconditionally propagate all AWS client exceptions, a transient failure halfway through provisioning (for instance, if _create_delivery_stream fails after the S3 bucket is created) will cause subsequent retries to fail immediately. On the next attempt, s3.create_bucket will raise a BucketAlreadyOwnedByYou (or similar) exception, which propagates and halts execution before the stream can be created.

To ensure the provisioning workflow can safely recover from partial failures, either catch and handle "already exists" exceptions in the helper functions to restore idempotency, or explicitly check for resource existence here before attempting creation.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: f42141b3-6a0e-4f6f-832c-eb7fc8397be9

📥 Commits

Reviewing files that changed from the base of the PR and between d9291a6 and 7e3bb42.

📒 Files selected for processing (3)
  • api/experimentation/ingestion_infra_service.py
  • api/tests/unit/experimentation/test_ingestion_infra_service.py
  • docs/docs/deployment-self-hosting/observability/_events-catalogue.md

@themis-blindfold

Copy link
Copy Markdown

⚖️ Themis judgement: ✅ Ship it

Well-structured service layer for provisioning per-organisation S3 event buckets and Firehose delivery streams. The create-then-reconcile pattern for the bucket (public access block and lifecycle reapplied on every call) is a good security habit, and the deliberate create-only semantics for the stream are documented in the docstring. Error handling correctly distinguishes "resource already exists" from real failures in both S3 and Firehose paths. Tests are thorough — happy path with full destination config verification, idempotency, header injection for account-regional namespace, settings guard, and error propagation for both AWS services.

🎯 Correctness 5/5
🧪 Test coverage 4/5
📐 Code quality 5/5
🚀 Product impact 3/5

Test coverage gets a 4 because the main integration test does heavy lifting (full destination config assertion, lifecycle, public access block, log events), but there are no direct unit tests for get_bucket_name/get_stream_name — only exercised through the integration path. Minor gap given how well the integration test covers them.

📝 Walkthrough
  • Ingestion infra service (api/experimentation/ingestion_infra_service.py) — new module that idempotently provisions an S3 events bucket (account-regional namespace, public access blocked, 30-day lifecycle) and a DirectPut Firehose delivery stream (dynamic partitioning by environment_key, GZIP, 64 MiB buffer) per organisation.
  • Dataclass (api/experimentation/dataclasses.py) — IngestionInfrastructure frozen dataclass to return bucket and stream names.
  • Settings (api/app/settings/common.py) — INGESTION_FIREHOSE_DELIVERY_ROLE_ARN env var, defaulting to empty string (service raises ImproperlyConfigured when unset).
  • Tests (api/tests/unit/experimentation/test_ingestion_infra_service.py) — six tests covering fresh provisioning, idempotency, namespace header, settings guard, and S3/Firehose error propagation via moto and mocker.
  • Infrastructure — ECS task definitions for staging and production set the new env var to the per-account Firehose delivery role ARN.
  • Docs — events catalogue updated with ingestion_infra.bucket_created and ingestion_infra.stream_created entries.
🧪 How to verify
  1. Run the experimentation unit suite: pytest api/tests/unit/experimentation/test_ingestion_infra_service.py -v — all six tests should pass.
  2. Verify the full experimentation suite still passes: pytest api/tests/unit/experimentation/ -v.
  3. Confirm the settings default is safe: start a Django shell without INGESTION_FIREHOSE_DELIVERY_ROLE_ARN set and call provision_ingestion_infrastructure(1) — it should raise ImproperlyConfigured.
  4. Inspect the ECS task definition diffs to confirm staging and production role ARNs point to the correct AWS accounts (302456015006 for staging, 084060095745 for production).

Automate: CI already covers steps 1–2 via the API Unit Tests checks (passing on 3.11, 3.12, 3.13).

Product take: Infrastructure plumbing for per-organisation experiment event ingestion — no user-visible change yet, but it lays the foundation for the experimentation data pipeline. Solid improvement to the platform's experimentation capabilities once wired up.

🧭 Assumptions & unverified claims
  • The code comment claims S3 account-regional namespace buckets must follow a {prefix}-{account_id}-{region}-an naming convention with single hyphens. Could not verify against AWS documentation whether single hyphens are accepted or double hyphens (--) are required. The x-amz-bucket-namespace: account-regional header is correctly injected, which may be sufficient regardless of name format.
  • The PR description lists INGESTION_EVENTS_BUCKET_PREFIX as a new setting, but the bucket prefix is hardcoded as BUCKET_NAME_PREFIX in the module. The description appears inaccurate on this point; the code is internally consistent.

A service that provisions its own buckets and streams — the infrastructure is bootstrapping itself, one org at a time. · reviewed at d9291a6

@Zaimwa9 Zaimwa9 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 comments more than requesting changes. For the create flow, a comment would be satisfying imo.
For the tags, it looks interesting to keep track of the costs precisely

Comment thread api/experimentation/ingestion_infra_service.py
Comment thread api/experimentation/ingestion_infra_service.py
Add an organisation_id cost-allocation tag to the per-organisation S3 bucket
and Firehose delivery stream so AWS billing can be attributed per organisation.
@github-actions github-actions Bot added docs Documentation updates infrastructure labels Jul 21, 2026
@github-actions github-actions Bot added feature New feature or request and removed feature New feature or request infrastructure docs Documentation updates labels Jul 21, 2026
@github-actions github-actions Bot added docs Documentation updates infrastructure feature New feature or request and removed feature New feature or request infrastructure docs Documentation updates labels Jul 21, 2026
@gagantrivedi
gagantrivedi requested a review from Zaimwa9 July 21, 2026 05:55
@gagantrivedi
gagantrivedi merged commit 7266074 into main Jul 21, 2026
35 checks passed
@gagantrivedi
gagantrivedi deleted the feat/experimentation-analytics-infra-service branch July 21, 2026 06:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

api Issue related to the REST API feature New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants