diff --git a/libcxx/include/__format/buffer.h b/libcxx/include/__format/buffer.h
--- a/libcxx/include/__format/buffer.h
+++ b/libcxx/include/__format/buffer.h
@@ -207,6 +207,40 @@
   size_t __size_{0};
 };
 
+/// A buffer that counts and limits the number of insertions.
+///
+/// This buffer holds another buffer to do the actual insertions until the
+/// requested maximum has been reached. Once the maximum is reached it only
+/// keeps track of the number of additional insertions.
+template <class _OutIt, __formatter::__char_type _CharT>
+requires(output_iterator<_OutIt, const _CharT&>) class _LIBCPP_TEMPLATE_VIS
+    __format_to_n_buffer {
+  using _Buffer = typename __buffer_selector<_OutIt, _CharT>::type;
+  using _Size = iter_difference_t<_OutIt>;
+
+public:
+  _LIBCPP_HIDE_FROM_ABI explicit __format_to_n_buffer(_OutIt __out_it,
+                                                      _Size __n)
+      : __buffer_(_VSTD::move(__out_it)), __n_(__n) {}
+
+  _LIBCPP_HIDE_FROM_ABI void put(_CharT __c) {
+    ++__size_;
+    if (__size_ <= __n_)
+      __buffer_.put(__c);
+  }
+
+  _LIBCPP_HIDE_FROM_ABI _OutIt out() { return __buffer_.out(); }
+
+  _LIBCPP_HIDE_FROM_ABI _Size formatted_size() const noexcept {
+    return __size_;
+  }
+
+private:
+  _Buffer __buffer_;
+  _Size __n_;
+  _Size __size_{0};
+};
+
 } // namespace __format
 
 #endif // !defined(_LIBCPP_HAS_NO_CONCEPTS)
diff --git a/libcxx/include/format b/libcxx/include/format
--- a/libcxx/include/format
+++ b/libcxx/include/format
@@ -583,26 +583,28 @@
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, string_view __fmt,
             const _Args&... __args) {
-  // TODO FMT Improve PoC: using std::string is inefficient.
-  string __str = _VSTD::vformat(__fmt, _VSTD::make_format_args(__args...));
-  iter_difference_t<_OutIt> __s = __str.size();
-  iter_difference_t<_OutIt> __m =
-      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
-  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
-  return {_VSTD::move(__out_it), __s};
+
+  using _Buffer = __format::__format_to_n_buffer<_OutIt, char>;
+  _Buffer __buffer{_VSTD::move(__out_it), __n};
+  _VSTD::__vformat_to(
+      __format::__output_iterator<char>{&__format::__put<_Buffer, char>,
+                                        &__buffer},
+      __fmt, basic_format_args{_VSTD::make_format_args(__args...)});
+  return {__buffer.out(), __buffer.formatted_size()};
 }
 
 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, wstring_view __fmt,
             const _Args&... __args) {
-  // TODO FMT Improve PoC: using std::string is inefficient.
-  wstring __str = _VSTD::vformat(__fmt, _VSTD::make_wformat_args(__args...));
-  iter_difference_t<_OutIt> __s = __str.size();
-  iter_difference_t<_OutIt> __m =
-      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
-  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
-  return {_VSTD::move(__out_it), __s};
+
+  using _Buffer = __format::__format_to_n_buffer<_OutIt, wchar_t>;
+  _Buffer __buffer{_VSTD::move(__out_it), __n};
+  _VSTD::__vformat_to(
+      __format::__output_iterator<wchar_t>{&__format::__put<_Buffer, wchar_t>,
+                                           &__buffer},
+      __fmt, basic_format_args{_VSTD::make_wformat_args(__args...)});
+  return {__buffer.out(), __buffer.formatted_size()};
 }
 
 template <class... _Args>
@@ -726,28 +728,30 @@
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
             string_view __fmt, const _Args&... __args) {
-  // TODO FMT Improve PoC: using std::string is inefficient.
-  string __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
-                                _VSTD::make_format_args(__args...));
-  iter_difference_t<_OutIt> __s = __str.size();
-  iter_difference_t<_OutIt> __m =
-      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
-  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
-  return {_VSTD::move(__out_it), __s};
+
+  using _Buffer = __format::__format_to_n_buffer<_OutIt, char>;
+  _Buffer __buffer{_VSTD::move(__out_it), __n};
+  _VSTD::__vformat_to(
+      __format::__output_iterator<char>{&__format::__put<_Buffer, char>,
+                                        &__buffer},
+      _VSTD::move(__loc), __fmt,
+      basic_format_args{_VSTD::make_format_args(__args...)});
+  return {__buffer.out(), __buffer.formatted_size()};
 }
 
 template <output_iterator<const wchar_t&> _OutIt, class... _Args>
 _LIBCPP_HIDE_FROM_ABI _LIBCPP_AVAILABILITY_FORMAT format_to_n_result<_OutIt>
 format_to_n(_OutIt __out_it, iter_difference_t<_OutIt> __n, locale __loc,
             wstring_view __fmt, const _Args&... __args) {
-  // TODO FMT Improve PoC: using std::string is inefficient.
-  wstring __str = _VSTD::vformat(_VSTD::move(__loc), __fmt,
-                                 _VSTD::make_wformat_args(__args...));
-  iter_difference_t<_OutIt> __s = __str.size();
-  iter_difference_t<_OutIt> __m =
-      _VSTD::clamp(__n, iter_difference_t<_OutIt>(0), __s);
-  __out_it = _VSTD::copy_n(__str.begin(), __m, _VSTD::move(__out_it));
-  return {_VSTD::move(__out_it), __s};
+
+  using _Buffer = __format::__format_to_n_buffer<_OutIt, wchar_t>;
+  _Buffer __buffer{_VSTD::move(__out_it), __n};
+  _VSTD::__vformat_to(
+      __format::__output_iterator<wchar_t>{&__format::__put<_Buffer, wchar_t>,
+                                           &__buffer},
+      _VSTD::move(__loc), __fmt,
+      basic_format_args{_VSTD::make_wformat_args(__args...)});
+  return {__buffer.out(), __buffer.formatted_size()};
 }
 
 template <class... _Args>