diff --git a/ts/flexbuffers/builder.ts b/ts/flexbuffers/builder.ts
new file mode 100644
index 0000000..4321547
--- /dev/null
+++ b/ts/flexbuffers/builder.ts
@@ -0,0 +1,549 @@
+import { BitWidth } from './bit-width'
+import { paddingSize, iwidth, uwidth, fwidth, toByteWidth, fromByteWidth } from './bit-width-util'
+import { toUTF8Array } from './flexbuffers-util'
+import { ValueType } from './value-type'
+import { isNumber, isTypedVectorElement, toTypedVector } from './value-type-util'
+import { StackValue } from './stack-value'
+
+interface StackPointer {
+  stackPosition: number,
+  isVector: boolean
+  presorted?: boolean
+}
+
+export class Builder {
+  buffer: ArrayBuffer
+  view: DataView
+
+  readonly stack: Array<StackValue> = [];
+  readonly stackPointers: Array<StackPointer> = [];
+  offset = 0;
+  finished = false;
+  readonly stringLookup: Record<string, StackValue> = {};
+  readonly keyLookup: Record<string, StackValue> = {};
+  readonly keyVectorLookup: Record<string, StackValue> = {};
+  readonly indirectIntLookup: Record<number, StackValue> = {};
+  readonly indirectUIntLookup: Record<number, StackValue> = {};
+  readonly indirectFloatLookup: Record<number, StackValue> = {};
+
+  constructor(size = 2048, private dedupStrings = true, private dedupKeys = true, private dedupKeyVectors = true) {
+    this.buffer = new ArrayBuffer(size > 0 ? size : 2048);
+    this.view = new DataView(this.buffer);
+  }
+
+  private align(width: BitWidth) {
+    const byteWidth = toByteWidth(width);
+    this.offset += paddingSize(this.offset, byteWidth);
+    return byteWidth;
+  }
+
+  computeOffset(newValueSize: number): number {
+    const targetOffset = this.offset + newValueSize;
+    let size = this.buffer.byteLength;
+    const prevSize = size;
+    while (size < targetOffset) {
+      size <<= 1;
+    }
+    if (prevSize < size) {
+      const prevBuffer = this.buffer;
+      this.buffer = new ArrayBuffer(size);
+      this.view = new DataView(this.buffer);
+      new Uint8Array(this.buffer).set(new Uint8Array(prevBuffer), 0);
+    }
+    return targetOffset;
+  }
+
+  pushInt(value: number, width: BitWidth): void {
+    if (width === BitWidth.WIDTH8) {
+      this.view.setInt8(this.offset, value);
+    } else if (width === BitWidth.WIDTH16) {
+      this.view.setInt16(this.offset, value, true);
+    } else if (width === BitWidth.WIDTH32) {
+      this.view.setInt32(this.offset, value, true);
+    } else if (width === BitWidth.WIDTH64) {
+      this.view.setBigInt64(this.offset, BigInt(value), true);
+    } else {
+      throw `Unexpected width: ${width} for value: ${value}`;
+    }
+  }
+
+  pushUInt(value: number, width: BitWidth): void {
+    if (width === BitWidth.WIDTH8) {
+      this.view.setUint8(this.offset, value);
+    } else if (width === BitWidth.WIDTH16) {
+      this.view.setUint16(this.offset, value, true);
+    } else if (width === BitWidth.WIDTH32) {
+      this.view.setUint32(this.offset, value, true);
+    } else if (width === BitWidth.WIDTH64) {
+      this.view.setBigUint64(this.offset, BigInt(value), true);
+    } else {
+      throw `Unexpected width: ${width} for value: ${value}`;
+    }
+  }
+
+  private writeInt(value: number, byteWidth: number) {
+    const newOffset = this.computeOffset(byteWidth);
+    this.pushInt(value, fromByteWidth(byteWidth));
+    this.offset = newOffset;
+  }
+
+  private writeUInt(value: number, byteWidth: number) {
+    const newOffset = this.computeOffset(byteWidth);
+    this.pushUInt(value, fromByteWidth(byteWidth));
+    this.offset = newOffset;
+  }
+
+  private writeBlob(arrayBuffer: ArrayBuffer) {
+    const length = arrayBuffer.byteLength;
+    const bitWidth = uwidth(length);
+    const byteWidth = this.align(bitWidth);
+    this.writeUInt(length, byteWidth);
+    const blobOffset = this.offset;
+    const newOffset = this.computeOffset(length);
+    new Uint8Array(this.buffer).set(new Uint8Array(arrayBuffer), blobOffset);
+    this.stack.push(this.offsetStackValue(blobOffset, ValueType.BLOB, bitWidth));
+    this.offset = newOffset;
+  }
+
+  private writeString(str: string): void {
+    if (this.dedupStrings && Object.prototype.hasOwnProperty.call(this.stringLookup, str)) {
+      this.stack.push(this.stringLookup[str]);
+      return;
+    }
+    const utf8 = toUTF8Array(str);
+    const length = utf8.length;
+    const bitWidth = uwidth(length);
+    const byteWidth = this.align(bitWidth);
+    this.writeUInt(length, byteWidth);
+    const stringOffset = this.offset;
+    const newOffset = this.computeOffset(length + 1);
+    new Uint8Array(this.buffer).set(utf8, stringOffset);
+    const stackValue = this.offsetStackValue(stringOffset, ValueType.STRING, bitWidth);
+    this.stack.push(stackValue);
+    if (this.dedupStrings) {
+      this.stringLookup[str] = stackValue;
+    }
+    this.offset = newOffset;
+  }
+
+  private writeKey(str: string): void {
+    if (this.dedupKeys && Object.prototype.hasOwnProperty.call(this.keyLookup, str)) {
+      this.stack.push(this.keyLookup[str]);
+      return;
+    }
+    const utf8 = toUTF8Array(str);
+    const length = utf8.length;
+    const newOffset = this.computeOffset(length + 1);
+    new Uint8Array(this.buffer).set(utf8, this.offset);
+    const stackValue = this.offsetStackValue(this.offset, ValueType.KEY, BitWidth.WIDTH8);
+    this.stack.push(stackValue);
+    if (this.dedupKeys) {
+      this.keyLookup[str] = stackValue;
+    }
+    this.offset = newOffset;
+  }
+
+  private writeStackValue(value: StackValue, byteWidth: number): void {
+    const newOffset = this.computeOffset(byteWidth);
+    if (value.isOffset()) {
+      const relativeOffset = this.offset - value.offset;
+      if (byteWidth === 8 || BigInt(relativeOffset) < (BigInt(1) << BigInt(byteWidth * 8))) {
+        this.writeUInt(relativeOffset, byteWidth);
+      } else {
+        throw `Unexpected size ${byteWidth}. This might be a bug. Please create an issue https://github.com/google/flatbuffers/issues/new`
+      }
+    } else {
+      value.writeToBuffer(byteWidth);
+    }
+    this.offset = newOffset;
+  }
+
+  private integrityCheckOnValueAddition() {
+    if (this.finished) {
+      throw "Adding values after finish is prohibited";
+    }
+    if (this.stackPointers.length !== 0 && this.stackPointers[this.stackPointers.length - 1].isVector === false) {
+      if (this.stack[this.stack.length - 1].type !== ValueType.KEY) {
+        throw "Adding value to a map before adding a key is prohibited";
+      }
+    }
+  }
+
+  private integrityCheckOnKeyAddition() {
+    if (this.finished) {
+      throw "Adding values after finish is prohibited";
+    }
+    if (this.stackPointers.length === 0 || this.stackPointers[this.stackPointers.length - 1].isVector) {
+      throw "Adding key before starting a map is prohibited";
+    }
+  }
+
+  startVector(): void {
+    this.stackPointers.push({ stackPosition: this.stack.length, isVector: true });
+  }
+
+  startMap(presorted = false): void {
+    this.stackPointers.push({ stackPosition: this.stack.length, isVector: false, presorted: presorted });
+  }
+
+  private endVector(stackPointer: StackPointer) {
+    const vecLength = this.stack.length - stackPointer.stackPosition;
+    const vec = this.createVector(stackPointer.stackPosition, vecLength, 1);
+    this.stack.splice(stackPointer.stackPosition, vecLength);
+    this.stack.push(vec);
+  }
+
+  private endMap(stackPointer: StackPointer) {
+    if (!stackPointer.presorted) {
+      this.sort(stackPointer);
+    }
+    let keyVectorHash = "";
+    for (let i = stackPointer.stackPosition; i < this.stack.length; i += 2) {
+      keyVectorHash += `,${this.stack[i].offset}`;
+    }
+    const vecLength = (this.stack.length - stackPointer.stackPosition) >> 1;
+
+    if (this.dedupKeyVectors && !Object.prototype.hasOwnProperty.call(this.keyVectorLookup, keyVectorHash)) {
+      this.keyVectorLookup[keyVectorHash] = this.createVector(stackPointer.stackPosition, vecLength, 2);
+    }
+    const keysStackValue = this.dedupKeyVectors ? this.keyVectorLookup[keyVectorHash] : this.createVector(stackPointer.stackPosition, vecLength, 2);
+    const valuesStackValue = this.createVector(stackPointer.stackPosition + 1, vecLength, 2, keysStackValue);
+    this.stack.splice(stackPointer.stackPosition, vecLength << 1);
+    this.stack.push(valuesStackValue);
+  }
+
+  private sort(stackPointer: StackPointer) {
+    const view = this.view
+    const stack = this.stack
+
+    function shouldFlip(v1: StackValue, v2: StackValue) {
+      if (v1.type !== ValueType.KEY || v2.type !== ValueType.KEY) {
+        throw `Stack values are not keys ${v1} | ${v2}. Check if you combined [addKey] with add... method calls properly.`
+      }
+      let c1, c2;
+      let index = 0;
+      do {
+        c1 = view.getUint8(v1.offset + index);
+        c2 = view.getUint8(v2.offset + index);
+        if (c2 < c1) return true;
+        if (c1 < c2) return false;
+        index += 1;
+      } while (c1 !== 0 && c2 !== 0);
+      return false;
+    }
+
+    function swap(stack: Array<StackValue>, flipIndex: number, i: number) {
+      if (flipIndex === i) return;
+      const k = stack[flipIndex];
+      const v = stack[flipIndex + 1];
+      stack[flipIndex] = stack[i];
+      stack[flipIndex + 1] = stack[i + 1];
+      stack[i] = k;
+      stack[i + 1] = v;
+    }
+
+    function selectionSort() {
+      for (let i = stackPointer.stackPosition; i < stack.length; i += 2) {
+        let flipIndex = i;
+        for (let j = i + 2; j < stack.length; j += 2) {
+          if (shouldFlip(stack[flipIndex], stack[j])) {
+            flipIndex = j;
+          }
+        }
+        if (flipIndex !== i) {
+          swap(stack, flipIndex, i);
+        }
+      }
+    }
+
+    function smaller(v1: StackValue, v2: StackValue) {
+      if (v1.type !== ValueType.KEY || v2.type !== ValueType.KEY) {
+        throw `Stack values are not keys ${v1} | ${v2}. Check if you combined [addKey] with add... method calls properly.`
+      }
+      if (v1.offset === v2.offset) {
+        return false;
+      }
+      let c1, c2;
+      let index = 0;
+      do {
+        c1 = view.getUint8(v1.offset + index);
+        c2 = view.getUint8(v2.offset + index);
+        if (c1 < c2) return true;
+        if (c2 < c1) return false;
+        index += 1;
+      } while (c1 !== 0 && c2 !== 0);
+      return false;
+    }
+
+    function quickSort(left: number, right: number) {
+
+      if (left < right) {
+        const mid = left + (((right - left) >> 2)) * 2;
+        const pivot = stack[mid];
+        let left_new = left;
+        let right_new = right;
+
+        do {
+          while (smaller(stack[left_new], pivot)) {
+            left_new += 2;
+          }
+          while (smaller(pivot, stack[right_new])) {
+            right_new -= 2;
+          }
+          if (left_new <= right_new) {
+            swap(stack, left_new, right_new);
+            left_new += 2;
+            right_new -= 2;
+          }
+        } while (left_new <= right_new);
+
+        quickSort(left, right_new);
+        quickSort(left_new, right);
+
+      }
+    }
+
+    let sorted = true;
+    for (let i = stackPointer.stackPosition; i < this.stack.length - 2; i += 2) {
+      if (shouldFlip(this.stack[i], this.stack[i + 2])) {
+        sorted = false;
+        break;
+      }
+    }
+
+    if (!sorted) {
+      if (this.stack.length - stackPointer.stackPosition > 40) {
+        quickSort(stackPointer.stackPosition, this.stack.length - 2);
+      } else {
+        selectionSort();
+      }
+    }
+  }
+
+  end(): void {
+    if (this.stackPointers.length < 1) return;
+    const pointer = this.stackPointers.pop() as StackPointer;
+    if (pointer.isVector) {
+      this.endVector(pointer);
+    } else {
+      this.endMap(pointer);
+    }
+  }
+
+  private createVector(start: number, vecLength: number, step: number, keys: StackValue | null = null) {
+    let bitWidth = uwidth(vecLength);
+    let prefixElements = 1;
+    if (keys !== null) {
+      const elementWidth = keys.elementWidth(this.offset, 0);
+      if (elementWidth > bitWidth) {
+        bitWidth = elementWidth;
+      }
+      prefixElements += 2;
+    }
+    let vectorType = ValueType.KEY;
+    let typed = keys === null;
+    for (let i = start; i < this.stack.length; i += step) {
+      const elementWidth = this.stack[i].elementWidth(this.offset, i + prefixElements);
+      if (elementWidth > bitWidth) {
+        bitWidth = elementWidth;
+      }
+      if (i === start) {
+        vectorType = this.stack[i].type;
+        typed = typed && isTypedVectorElement(vectorType);
+      } else {
+        if (vectorType !== this.stack[i].type) {
+          typed = false;
+        }
+      }
+    }
+    const byteWidth = this.align(bitWidth);
+    const fix = typed && isNumber(vectorType) && vecLength >= 2 && vecLength <= 4;
+    if (keys !== null) {
+      this.writeStackValue(keys, byteWidth);
+      this.writeUInt(1 << keys.width, byteWidth);
+    }
+    if (!fix) {
+      this.writeUInt(vecLength, byteWidth);
+    }
+    const vecOffset = this.offset;
+    for (let i = start; i < this.stack.length; i += step) {
+      this.writeStackValue(this.stack[i], byteWidth);
+    }
+    if (!typed) {
+      for (let i = start; i < this.stack.length; i += step) {
+        this.writeUInt(this.stack[i].storedPackedType(), 1);
+      }
+    }
+    if (keys !== null) {
+      return this.offsetStackValue(vecOffset, ValueType.MAP, bitWidth);
+    }
+    if (typed) {
+      const vType = toTypedVector(vectorType, fix ? vecLength : 0);
+      return this.offsetStackValue(vecOffset, vType, bitWidth);
+    }
+    return this.offsetStackValue(vecOffset, ValueType.VECTOR, bitWidth);
+  }
+
+  private nullStackValue() {
+    return new StackValue(this, ValueType.NULL, BitWidth.WIDTH8);
+  }
+
+  private boolStackValue(value: boolean) {
+    return new StackValue(this, ValueType.BOOL, BitWidth.WIDTH8, value);
+  }
+
+  private intStackValue(value: number | bigint) {
+    return new StackValue(this, ValueType.INT, iwidth(value), value as number);
+  }
+
+  private uintStackValue(value: number) {
+    return new StackValue(this, ValueType.UINT, uwidth(value), value);
+  }
+
+  private floatStackValue(value: number) {
+    return new StackValue(this, ValueType.FLOAT, fwidth(value), value);
+  }
+
+  private offsetStackValue(offset: number, valueType: ValueType, bitWidth: BitWidth): StackValue {
+    return new StackValue(this, valueType, bitWidth, null, offset);
+  }
+
+  private finishBuffer() {
+    if (this.stack.length !== 1) {
+      throw `Stack has to be exactly 1, but it is ${this.stack.length}. You have to end all started vectors and maps before calling [finish]`;
+    }
+    const value = this.stack[0];
+    const byteWidth = this.align(value.elementWidth(this.offset, 0));
+    this.writeStackValue(value, byteWidth);
+    this.writeUInt(value.storedPackedType(), 1);
+    this.writeUInt(byteWidth, 1);
+    this.finished = true;
+  }
+
+  add(value: undefined | null | boolean | bigint | number | DataView | string | Array<unknown> | Record<string, unknown> | unknown): void {
+    this.integrityCheckOnValueAddition();
+    if (typeof value === 'undefined') {
+      throw "You need to provide a value";
+    }
+    if (value === null) {
+      this.stack.push(this.nullStackValue());
+    } else if (typeof value === "boolean") {
+      this.stack.push(this.boolStackValue(value));
+    } else if (typeof value === "bigint") {
+      this.stack.push(this.intStackValue(value));
+    } else if (typeof value == 'number') {
+      if (Number.isInteger(value)) {
+        this.stack.push(this.intStackValue(value));
+      } else {
+        this.stack.push(this.floatStackValue(value));
+      }
+    } else if (ArrayBuffer.isView(value)) {
+      this.writeBlob(value.buffer);
+    } else if (typeof value === 'string' || value instanceof String) {
+      this.writeString(value as string);
+    } else if (Array.isArray(value)) {
+      this.startVector();
+      for (let i = 0; i < value.length; i++) {
+        this.add(value[i]);
+      }
+      this.end();
+    } else if (typeof value === 'object') {
+      const properties = Object.getOwnPropertyNames(value).sort();
+      this.startMap(true);
+      for (let i = 0; i < properties.length; i++) {
+        const key = properties[i];
+        this.addKey(key);
+        this.add((value as Record<string, unknown>)[key]);
+      }
+      this.end();
+    } else {
+      throw `Unexpected value input ${value}`;
+    }
+  }
+
+  finish(): Uint8Array {
+    if (!this.finished) {
+      this.finishBuffer();
+    }
+    const result = this.buffer.slice(0, this.offset);
+    return new Uint8Array(result);
+  }
+
+  isFinished(): boolean {
+    return this.finished;
+  }
+
+  addKey(key: string): void {
+    this.integrityCheckOnKeyAddition();
+    this.writeKey(key);
+  }
+
+  addInt(value: number, indirect = false, deduplicate = false): void {
+    this.integrityCheckOnValueAddition();
+    if (!indirect) {
+      this.stack.push(this.intStackValue(value));
+      return;
+    }
+    if (deduplicate && Object.prototype.hasOwnProperty.call(this.indirectIntLookup, value)) {
+      this.stack.push(this.indirectIntLookup[value]);
+      return;
+    }
+    const stackValue = this.intStackValue(value);
+    const byteWidth = this.align(stackValue.width);
+    const newOffset = this.computeOffset(byteWidth);
+    const valueOffset = this.offset;
+    stackValue.writeToBuffer(byteWidth);
+    const stackOffset = this.offsetStackValue(valueOffset, ValueType.INDIRECT_INT, stackValue.width);
+    this.stack.push(stackOffset);
+    this.offset = newOffset;
+    if (deduplicate) {
+      this.indirectIntLookup[value] = stackOffset;
+    }
+  }
+
+  addUInt(value: number, indirect = false, deduplicate = false): void {
+    this.integrityCheckOnValueAddition();
+    if (!indirect) {
+      this.stack.push(this.uintStackValue(value));
+      return;
+    }
+    if (deduplicate && Object.prototype.hasOwnProperty.call(this.indirectUIntLookup, value)) {
+      this.stack.push(this.indirectUIntLookup[value]);
+      return;
+    }
+    const stackValue = this.uintStackValue(value);
+    const byteWidth = this.align(stackValue.width);
+    const newOffset = this.computeOffset(byteWidth);
+    const valueOffset = this.offset;
+    stackValue.writeToBuffer(byteWidth);
+    const stackOffset = this.offsetStackValue(valueOffset, ValueType.INDIRECT_UINT, stackValue.width);
+    this.stack.push(stackOffset);
+    this.offset = newOffset;
+    if (deduplicate) {
+      this.indirectUIntLookup[value] = stackOffset;
+    }
+  }
+
+  addFloat(value: number, indirect = false, deduplicate = false): void {
+    this.integrityCheckOnValueAddition();
+    if (!indirect) {
+      this.stack.push(this.floatStackValue(value));
+      return;
+    }
+    if (deduplicate && Object.prototype.hasOwnProperty.call(this.indirectFloatLookup, value)) {
+      this.stack.push(this.indirectFloatLookup[value]);
+      return;
+    }
+    const stackValue = this.floatStackValue(value);
+    const byteWidth = this.align(stackValue.width);
+    const newOffset = this.computeOffset(byteWidth);
+    const valueOffset = this.offset;
+    stackValue.writeToBuffer(byteWidth);
+    const stackOffset = this.offsetStackValue(valueOffset, ValueType.INDIRECT_FLOAT, stackValue.width);
+    this.stack.push(stackOffset);
+    this.offset = newOffset;
+    if (deduplicate) {
+      this.indirectFloatLookup[value] = stackOffset;
+    }
+  }
+}
