diff --git a/.changeset/metric-table-autofill-on-database-change.md b/.changeset/metric-table-autofill-on-database-change.md
new file mode 100644
index 0000000000..cd349fc59c
--- /dev/null
+++ b/.changeset/metric-table-autofill-on-database-change.md
@@ -0,0 +1,5 @@
+---
+'@hyperdx/app': patch
+---
+
+fix: Only auto-detect metric tables when the database selection changes
diff --git a/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx b/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx
index 2a462bc988..5e4021d659 100644
--- a/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx
+++ b/packages/app/src/components/Sources/SourceForm/MetricTableModelForm.tsx
@@ -1,6 +1,6 @@
import { useEffect, useRef } from 'react';
import { useWatch } from 'react-hook-form';
-import { MetricsDataType } from '@hyperdx/common-utils/dist/types';
+import { MetricsDataType, SourceKind } from '@hyperdx/common-utils/dist/types';
import { Stack, Text } from '@mantine/core';
import { notifications } from '@mantine/notifications';
@@ -10,7 +10,7 @@ import { DBTableSelectControlled } from '@/components/DBTableSelect';
import { SourceSelectControlled } from '@/components/SourceSelect';
import { useMetadataWithSettings } from '@/hooks/useMetadata';
import { useMetricsSeriesTableAvailability } from '@/hooks/useMetricsSeriesTableAvailability';
-import { isValidMetricTable } from '@/source';
+import { isValidMetricTable, useSource } from '@/source';
import { useBrandDisplayName } from '@/theme/ThemeProvider';
import {
matchMetricTables,
@@ -21,7 +21,11 @@ import { DEFAULT_DATABASE, OTEL_CLICKHOUSE_EXPRESSIONS } from './constants';
import { FormRow } from './FormRow';
import { TableModelProps } from './types';
-export function MetricTableModelForm({ control, setValue }: TableModelProps) {
+export function MetricTableModelForm({
+ control,
+ setValue,
+ sourceId,
+}: TableModelProps) {
const brandName = useBrandDisplayName();
const { data: team } = api.useTeam();
const isMetricsSeriesTableEnabled = !!team?.isMetricsSeriesTableEnabled;
@@ -143,10 +147,31 @@ export function MetricTableModelForm({ control, setValue }: TableModelProps) {
{ enabled: !!databaseName && !!connectionId },
);
+ const { data: savedSource } = useSource({ id: sourceId });
+ const savedDatabaseName = savedSource?.from?.databaseName;
+ const wasSavedAsMetricSource = savedSource?.kind === SourceKind.Metric;
+ const isExistingSource = !!sourceId;
+
const lastAutofillKeyRef = useRef('');
+ const hasLoadedSavedSourceRef = useRef(false);
useEffect(() => {
const key = `${databaseName}:${connectionId}`;
+
+ if (isExistingSource && !hasLoadedSavedSourceRef.current) {
+ // Until the saved source lands in the form the watched values are still
+ // the new-source defaults, so nothing here reflects a user choice yet.
+ if (!savedSource) return;
+ if (savedDatabaseName && databaseName !== savedDatabaseName) return;
+ hasLoadedSavedSourceRef.current = true;
+ if (wasSavedAsMetricSource) {
+ // Treat the saved database as already handled — only a later switch to
+ // a different database triggers autofill.
+ lastAutofillKeyRef.current = key;
+ return;
+ }
+ }
+
if (key === lastAutofillKeyRef.current) return; // already ran for this db
const tableNames = tablesData?.data?.map((t: { name: string }) => t.name);
@@ -230,6 +255,10 @@ export function MetricTableModelForm({ control, setValue }: TableModelProps) {
connectionId,
metadata,
isMetricsSeriesTableEnabled,
+ isExistingSource,
+ savedSource,
+ savedDatabaseName,
+ wasSavedAsMetricSource,
]);
return (
diff --git a/packages/app/src/components/Sources/SourceForm/SourceForm.tsx b/packages/app/src/components/Sources/SourceForm/SourceForm.tsx
index e1d8a4c36f..4cb391eb76 100644
--- a/packages/app/src/components/Sources/SourceForm/SourceForm.tsx
+++ b/packages/app/src/components/Sources/SourceForm/SourceForm.tsx
@@ -728,7 +728,12 @@ export function TableSourceForm({
-
+
{onCancel && (