diff --git a/api/label/iterator.go b/api/label/iterator.go
index 6b345d092..ca852d500 100644
--- a/api/label/iterator.go
+++ b/api/label/iterator.go
@@ -25,6 +25,21 @@ type Iterator struct {
 	idx     int
 }
 
+// MergeIterator supports iterating over two sets of labels while
+// eliminating duplicate values from the combined set.  The first
+// iterator value takes precedence.
+type MergeItererator struct {
+	one     oneIterator
+	two     oneIterator
+	current kv.KeyValue
+}
+
+type oneIterator struct {
+	iter  Iterator
+	done  bool
+	label kv.KeyValue
+}
+
 // Next moves the iterator to the next position. Returns false if there
 // are no more labels.
 func (i *Iterator) Next() bool {
@@ -75,3 +90,64 @@ func (i *Iterator) ToSlice() []kv.KeyValue {
 	}
 	return slice
 }
+
+// NewMergeIterator returns a MergeIterator for merging two label set
+// iterators.  Duplicates are resolved by taking the value from the
+// first iterator.
+func NewMergeIterator(iter1, iter2 Iterator) MergeItererator {
+	mi := MergeItererator{
+		one: makeOne(iter1),
+		two: makeOne(iter2),
+	}
+	return mi
+}
+
+func makeOne(iter Iterator) oneIterator {
+	oi := oneIterator{
+		iter: iter,
+	}
+	oi.advance()
+	return oi
+}
+
+func (oi *oneIterator) advance() {
+	if oi.done = !oi.iter.Next(); !oi.done {
+		oi.label = oi.iter.Label()
+	}
+}
+
+// Next returns true if there is another label available.
+func (m *MergeItererator) Next() bool {
+	if m.one.done && m.two.done {
+		return false
+	}
+	if m.one.done {
+		m.current = m.two.label
+		m.two.advance()
+		return true
+	}
+	if m.two.done {
+		m.current = m.one.label
+		m.one.advance()
+		return true
+	}
+	if m.one.label.Key == m.two.label.Key {
+		m.current = m.one.label // first iterator label value wins
+		m.one.advance()
+		m.two.advance()
+		return true
+	}
+	if m.one.label.Key < m.two.label.Key {
+		m.current = m.one.label
+		m.one.advance()
+		return true
+	}
+	m.current = m.two.label
+	m.two.advance()
+	return true
+}
+
+// Label returns the current value after Next() returns true.
+func (m *MergeItererator) Label() kv.KeyValue {
+	return m.current
+}
diff --git a/api/label/iterator_test.go b/api/label/iterator_test.go
index 0548240f1..d0f7feece 100644
--- a/api/label/iterator_test.go
+++ b/api/label/iterator_test.go
@@ -15,6 +15,7 @@
 package label_test
 
 import (
+	"fmt"
 	"testing"
 
 	"go.opentelemetry.io/otel/api/kv"
@@ -55,3 +56,96 @@ func TestEmptyIterator(t *testing.T) {
 	require.Equal(t, 0, iter.Len())
 	require.False(t, iter.Next())
 }
+
+func TestMergedIterator(t *testing.T) {
+
+	type inputs struct {
+		name   string
+		keys1  []string
+		keys2  []string
+		expect []string
+	}
+
+	makeLabels := func(keys []string, num int) (result []kv.KeyValue) {
+		for _, k := range keys {
+			result = append(result, kv.Int(k, num))
+		}
+		return
+	}
+
+	for _, input := range []inputs{
+		{
+			name:   "one overlap",
+			keys1:  []string{"A", "B"},
+			keys2:  []string{"B", "C"},
+			expect: []string{"A/1", "B/1", "C/2"},
+		},
+		{
+			name:   "reversed one overlap",
+			keys1:  []string{"B", "A"},
+			keys2:  []string{"C", "B"},
+			expect: []string{"A/1", "B/1", "C/2"},
+		},
+		{
+			name:   "one empty",
+			keys1:  nil,
+			keys2:  []string{"C", "B"},
+			expect: []string{"B/2", "C/2"},
+		},
+		{
+			name:   "two empty",
+			keys1:  []string{"C", "B"},
+			keys2:  nil,
+			expect: []string{"B/1", "C/1"},
+		},
+		{
+			name:   "no overlap both",
+			keys1:  []string{"C"},
+			keys2:  []string{"B"},
+			expect: []string{"B/2", "C/1"},
+		},
+		{
+			name:   "one empty single two",
+			keys1:  nil,
+			keys2:  []string{"B"},
+			expect: []string{"B/2"},
+		},
+		{
+			name:   "two empty single one",
+			keys1:  []string{"A"},
+			keys2:  nil,
+			expect: []string{"A/1"},
+		},
+		{
+			name:   "all empty",
+			keys1:  nil,
+			keys2:  nil,
+			expect: nil,
+		},
+		{
+			name:   "full overlap",
+			keys1:  []string{"A", "B", "C", "D"},
+			keys2:  []string{"A", "B", "C", "D"},
+			expect: []string{"A/1", "B/1", "C/1", "D/1"},
+		},
+	} {
+		t.Run(input.name, func(t *testing.T) {
+			labels1 := makeLabels(input.keys1, 1)
+			labels2 := makeLabels(input.keys2, 2)
+
+			set1 := label.NewSet(labels1...)
+			set2 := label.NewSet(labels2...)
+
+			merge := label.NewMergeIterator(set1.Iter(), set2.Iter())
+
+			var result []string
+
+			for merge.Next() {
+				label := merge.Label()
+				result = append(result, fmt.Sprint(label.Key, "/", label.Value.Emit()))
+			}
+
+			require.Equal(t, input.expect, result)
+		})
+	}
+}