diff --git a/include/flatbuffers/flatbuffers.h b/include/flatbuffers/flatbuffers.h
index 528cb5758d39b77804f30ad190a957f5da8e0631..94e5816561a60dcb809e46af23b1cf429807ff0b 100644
--- a/include/flatbuffers/flatbuffers.h
+++ b/include/flatbuffers/flatbuffers.h
@@ -525,12 +525,14 @@ class DetachedBuffer {
 // Essentially, this supports 2 std::vectors in a single buffer.
 class vector_downward {
  public:
-  explicit vector_downward(size_t initial_size = 1024,
-                           Allocator *allocator = nullptr,
-                           bool own_allocator = false)
+  explicit vector_downward(size_t initial_size,
+                           Allocator *allocator,
+                           bool own_allocator,
+                           size_t buffer_minalign)
       : allocator_(allocator ? allocator : &DefaultAllocator::instance()),
         own_allocator_(own_allocator),
         initial_size_(initial_size),
+        buffer_minalign_(buffer_minalign),
         reserved_(0),
         buf_(nullptr),
         cur_(nullptr),
@@ -580,11 +582,6 @@ class vector_downward {
     return fb;
   }
 
-  size_t growth_policy(size_t bytes) {
-    return (bytes == 0) ? initial_size_
-                        : ((bytes / 2) & ~(AlignOf<largest_scalar_t>() - 1));
-  }
-
   size_t ensure_space(size_t len) {
     assert(cur_ >= scratch_ && scratch_ >= buf_);
     if (len > static_cast<size_t>(cur_ - scratch_)) { reallocate(len); }
@@ -667,6 +664,7 @@ class vector_downward {
   Allocator *allocator_;
   bool own_allocator_;
   size_t initial_size_;
+  size_t buffer_minalign_;
   size_t reserved_;
   uint8_t *buf_;
   uint8_t *cur_;  // Points at location between empty (below) and used (above).
@@ -677,9 +675,9 @@ class vector_downward {
     auto old_reserved = reserved_;
     auto old_size = size();
     auto old_scratch_size = scratch_size();
-    reserved_ += (std::max)(len, growth_policy(old_reserved));
-    FLATBUFFERS_CONSTEXPR size_t alignment = AlignOf<largest_scalar_t>();
-    reserved_ = (reserved_ + alignment - 1) & ~(alignment - 1);
+    reserved_ += (std::max)(len,
+                            old_reserved ? old_reserved / 2 : initial_size_);
+    reserved_ = (reserved_ + buffer_minalign_ - 1) & ~(buffer_minalign_ - 1);
     if (buf_) {
       buf_ = allocator_->reallocate_downward(buf_, old_reserved, reserved_,
                                              old_size, old_scratch_size);
@@ -726,10 +724,16 @@ class FlatBufferBuilder {
   /// a `DefaultAllocator`.
   /// @param[in] own_allocator Whether the builder/vector should own the
   /// allocator. Defaults to / `false`.
+  /// @param[in] buffer_minalign Force the buffer to be aligned to the given
+  /// minimum alignment upon reallocation. Only needed if you intend to store
+  /// types with custom alignment AND you wish to read the buffer in-place
+  /// directly after creation.
   explicit FlatBufferBuilder(size_t initial_size = 1024,
                              Allocator *allocator = nullptr,
-                             bool own_allocator = false)
-      : buf_(initial_size, allocator, own_allocator),
+                             bool own_allocator = false,
+                             size_t buffer_minalign =
+                                 AlignOf<largest_scalar_t>())
+      : buf_(initial_size, allocator, own_allocator, buffer_minalign),
         num_field_loc(0),
         max_voffset_(0),
         nested(false),
@@ -827,8 +831,12 @@ class FlatBufferBuilder {
   /// @cond FLATBUFFERS_INTERNAL
   void Pad(size_t num_bytes) { buf_.fill(num_bytes); }
 
-  void Align(size_t elem_size) {
+  void TrackMinAlign(size_t elem_size) {
     if (elem_size > minalign_) minalign_ = elem_size;
+  }
+
+  void Align(size_t elem_size) {
+    TrackMinAlign(elem_size);
     buf_.fill(PaddingBytes(buf_.size(), elem_size));
   }
 
@@ -1023,6 +1031,7 @@ class FlatBufferBuilder {
   // Aligns such that when "len" bytes are written, an object can be written
   // after it with "alignment" without padding.
   void PreAlign(size_t len, size_t alignment) {
+    TrackMinAlign(alignment);
     buf_.fill(PaddingBytes(GetSize() + len, alignment));
   }
   template<typename T> void PreAlign(size_t len) {
diff --git a/src/reflection.cpp b/src/reflection.cpp
index d93859fd20b74ef398af1ae1448c1e3243419477..d5bcef1b79d014e058a7a2c0db7e46fa721ff3a0 100644
--- a/src/reflection.cpp
+++ b/src/reflection.cpp
@@ -435,7 +435,7 @@ Offset<const Table *> CopyTable(FlatBufferBuilder &fbb,
             auto element_size = GetTypeSize(element_base_type);
             if (elemobjectdef && elemobjectdef->is_struct())
               element_size = elemobjectdef->bytesize();
-            fbb.StartVector(element_size, vec->size());
+            fbb.StartVector(vec->size(), element_size);
             fbb.PushBytes(vec->Data(), element_size * vec->size());
             offset = fbb.EndVector(vec->size());
             break;