Summary
util/mappers/engine.py:map_environment_to_engine loads every canonical project segment (project.segments.all() if ps.id == ps.version_of_id) into every environment document, including feature-specific segments (Segment.feature_id IS NOT NULL) that have no FeatureSegment pointing at them in this env.
_get_segment_feature_states already env-scopes each segment's feature-states list, so those segments end up in the doc as {id, name, rules, feature_states: []} — but their rules payload stays, and that's what drives per-env doc size.
Fix
After computing the per-env feature_states dict, filter project_segments to drop feature-specific segments with no entry in that dict:
project_segment_feature_states_by_segment_id = _get_segment_feature_states(...)
project_segments = [
s for s in project_segments
if s.feature_id is None
or project_segment_feature_states_by_segment_id.get(s.pk)
]
Safety
Feature-specific segments (Segment.feature_id IS NOT NULL) are schema-scoped to one feature and reach evaluation only via FeatureSegment(feature=F, segment=S, environment=E). If no such row exists for env E, S has no evaluation path in E. Project-wide segments (feature_id IS NULL) are unfiltered.
Impact
On one project we measured (178 envs, substantial feature-level targeting), this drops per-env feature-specific-segment count from ~8,270 to ~46 — large enough to fit a project that currently overflows DynamoDB's 400 KB BatchWriteItem limit.
Summary
util/mappers/engine.py:map_environment_to_engineloads every canonical project segment (project.segments.all() if ps.id == ps.version_of_id) into every environment document, including feature-specific segments (Segment.feature_id IS NOT NULL) that have noFeatureSegmentpointing at them in this env._get_segment_feature_statesalready env-scopes each segment's feature-states list, so those segments end up in the doc as{id, name, rules, feature_states: []}— but theirrulespayload stays, and that's what drives per-env doc size.Fix
After computing the per-env feature_states dict, filter
project_segmentsto drop feature-specific segments with no entry in that dict:Safety
Feature-specific segments (
Segment.feature_id IS NOT NULL) are schema-scoped to one feature and reach evaluation only viaFeatureSegment(feature=F, segment=S, environment=E). If no such row exists for env E, S has no evaluation path in E. Project-wide segments (feature_id IS NULL) are unfiltered.Impact
On one project we measured (178 envs, substantial feature-level targeting), this drops per-env feature-specific-segment count from ~8,270 to ~46 — large enough to fit a project that currently overflows DynamoDB's 400 KB
BatchWriteItemlimit.