diff --git a/ts/components/session/RegistrationTabs.tsx b/ts/components/session/RegistrationTabs.tsx
index e4d3ce1b2..0bf51680b 100644
--- a/ts/components/session/RegistrationTabs.tsx
+++ b/ts/components/session/RegistrationTabs.tsx
@@ -131,8 +131,8 @@ export class RegistrationTabs extends React.Component<any, State> {
   }
 
   public componentDidMount() {
-    this.generateMnemonicAndKeyPair().ignore();
-    this.resetRegistration().ignore();
+    void this.generateMnemonicAndKeyPair();
+    void this.resetRegistration();
   }
 
   public render() {
@@ -345,7 +345,7 @@ export class RegistrationTabs extends React.Component<any, State> {
       <SessionButton
         onClick={() => {
           if (signUpMode === SignUpMode.Default) {
-            this.onSignUpGenerateSessionIDClick().ignore();
+            this.onSignUpGenerateSessionIDClick();
           } else {
             this.onSignUpGetStartedClick();
           }
@@ -357,7 +357,7 @@ export class RegistrationTabs extends React.Component<any, State> {
     );
   }
 
-  private async onSignUpGenerateSessionIDClick() {
+  private onSignUpGenerateSessionIDClick() {
     this.setState(
       {
         signUpMode: SignUpMode.SessionIDShown,
@@ -375,7 +375,7 @@ export class RegistrationTabs extends React.Component<any, State> {
   }
 
   private onCompleteSignUpClick() {
-    this.register('english').ignore();
+    void this.register('english');
   }
 
   private renderSignIn() {
@@ -541,7 +541,7 @@ export class RegistrationTabs extends React.Component<any, State> {
 
   private handleContinueYourSessionClick() {
     if (this.state.signInMode === SignInMode.UsingRecoveryPhrase) {
-      this.register('english').ignore();
+      void this.register('english');
     }
   }
 
diff --git a/ts/components/session/SessionSeedModal.tsx b/ts/components/session/SessionSeedModal.tsx
index 0852a9411..539894e68 100644
--- a/ts/components/session/SessionSeedModal.tsx
+++ b/ts/components/session/SessionSeedModal.tsx
@@ -50,8 +50,8 @@ class SessionSeedModalInner extends React.Component<Props, State> {
   public render() {
     const i18n = window.i18n;
 
-    this.checkHasPassword();
-    this.getRecoveryPhrase().ignore();
+    void this.checkHasPassword();
+    void this.getRecoveryPhrase();
 
     const { onClose } = this.props;
     const { hasPassword, passwordValid } = this.state;
diff --git a/ts/components/session/conversation/SessionCompositionBox.tsx b/ts/components/session/conversation/SessionCompositionBox.tsx
index fb3b723c5..95f390601 100644
--- a/ts/components/session/conversation/SessionCompositionBox.tsx
+++ b/ts/components/session/conversation/SessionCompositionBox.tsx
@@ -520,7 +520,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
     }
     if (firstLink !== this.state.stagedLinkPreview?.url) {
       // trigger fetching of link preview data and image
-      void this.fetchLinkPreview(firstLink);
+      this.fetchLinkPreview(firstLink);
     }
 
     // if the fetch did not start yet, just don't show anything
@@ -553,7 +553,7 @@ export class SessionCompositionBox extends React.Component<Props, State> {
     return <></>;
   }
 
-  private async fetchLinkPreview(firstLink: string) {
+  private fetchLinkPreview(firstLink: string) {
     // mark the link preview as loading, no data are set yet
     this.setState({
       stagedLinkPreview: {
diff --git a/ts/components/session/conversation/SessionConversation.tsx b/ts/components/session/conversation/SessionConversation.tsx
index 2cb68faa0..eba3c7e61 100644
--- a/ts/components/session/conversation/SessionConversation.tsx
+++ b/ts/components/session/conversation/SessionConversation.tsx
@@ -824,7 +824,7 @@ export class SessionConversation extends React.Component<Props, State> {
     }
   }
 
-  private async showMessageDetails(messageProps: any) {
+  private showMessageDetails(messageProps: any) {
     messageProps.onDeleteMessage = async (id: string) => {
       await this.deleteMessagesById([id], false);
       this.setState({ messageDetailShowProps: undefined });
diff --git a/ts/components/session/conversation/SessionMessagesList.tsx b/ts/components/session/conversation/SessionMessagesList.tsx
index 3e84edc94..a4a9a0c26 100644
--- a/ts/components/session/conversation/SessionMessagesList.tsx
+++ b/ts/components/session/conversation/SessionMessagesList.tsx
@@ -41,7 +41,7 @@ interface Props {
     count: number;
   }) => void;
   replyToMessage: (messageId: number) => Promise<void>;
-  showMessageDetails: (messageProps: any) => Promise<void>;
+  showMessageDetails: (messageProps: any) => void;
   onClickAttachment: (attachment: any, message: any) => void;
   onDownloadAttachment: ({ attachment }: { attachment: any }) => void;
   onDeleteSelectedMessages: () => Promise<void>;
@@ -326,7 +326,7 @@ export class SessionMessagesList extends React.Component<Props, State> {
     messageProps.onReply = this.props.replyToMessage;
     messageProps.onShowDetail = async () => {
       const messageDetailsProps = await message.getPropsForMessageDetail();
-      void this.props.showMessageDetails(messageDetailsProps);
+      this.props.showMessageDetails(messageDetailsProps);
     };
 
     messageProps.onClickAttachment = (attachment: AttachmentType) => {
diff --git a/ts/components/session/conversation/SessionRecording.tsx b/ts/components/session/conversation/SessionRecording.tsx
index 053e808d4..065740865 100644
--- a/ts/components/session/conversation/SessionRecording.tsx
+++ b/ts/components/session/conversation/SessionRecording.tsx
@@ -122,9 +122,9 @@ class SessionRecordingInner extends React.Component<Props, State> {
     };
   }
 
-  public async componentWillMount() {
+  public componentWillMount() {
     // This turns on the microphone on the system. Later we need to turn it off.
-    await this.initiateRecordingStream();
+    this.initiateRecordingStream();
   }
 
   public componentDidMount() {
@@ -309,7 +309,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
     }
   }
 
-  private async stopRecording() {
+  private stopRecording() {
     this.setState({
       isRecording: false,
       isPaused: true,
@@ -436,7 +436,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
     this.props.sendVoiceMessage(audioBlob);
   }
 
-  private async initiateRecordingStream() {
+  private initiateRecordingStream() {
     navigator.getUserMedia(
       { audio: true },
       this.onRecordingStream,
@@ -462,7 +462,7 @@ class SessionRecordingInner extends React.Component<Props, State> {
     streamParams.stream.getTracks().forEach((track: any) => track.stop);
 
     // Stop recording
-    await this.stopRecording();
+    this.stopRecording();
   }
 
   private async onRecordingStream(stream: any) {
diff --git a/ts/components/session/conversation/SessionRightPanel.tsx b/ts/components/session/conversation/SessionRightPanel.tsx
index 47164cd0b..07c97d0cd 100644
--- a/ts/components/session/conversation/SessionRightPanel.tsx
+++ b/ts/components/session/conversation/SessionRightPanel.tsx
@@ -69,23 +69,23 @@ class SessionRightPanel extends React.Component<Props, State> {
   }
 
   public componentWillMount() {
-    this.getMediaGalleryProps()
-      .then(({ documents, media, onItemClick }) => {
+    void this.getMediaGalleryProps().then(
+      ({ documents, media, onItemClick }) => {
         this.setState({
           documents,
           media,
           onItemClick,
         });
-      })
-      .ignore();
+      }
+    );
   }
 
   public componentDidUpdate() {
     const mediaScanInterval = 1000;
 
     setTimeout(() => {
-      this.getMediaGalleryProps()
-        .then(({ documents, media, onItemClick }) => {
+      void this.getMediaGalleryProps().then(
+        ({ documents, media, onItemClick }) => {
           const { documents: oldDocs, media: oldMedias } = this.state;
           if (
             oldDocs.length !== documents.length ||
@@ -97,8 +97,8 @@ class SessionRightPanel extends React.Component<Props, State> {
               onItemClick,
             });
           }
-        })
-        .ignore();
+        }
+      );
     }, mediaScanInterval);
   }
 
@@ -193,7 +193,7 @@ class SessionRightPanel extends React.Component<Props, State> {
       }
     );
 
-    const saveAttachment = async ({ attachment, message }: any = {}) => {
+    const saveAttachment = ({ attachment, message }: any = {}) => {
       const timestamp = message.received_at;
       save({
         attachment,
@@ -203,10 +203,10 @@ class SessionRightPanel extends React.Component<Props, State> {
       });
     };
 
-    const onItemClick = async ({ message, attachment, type }: any) => {
+    const onItemClick = ({ message, attachment, type }: any) => {
       switch (type) {
         case 'documents': {
-          saveAttachment({ message, attachment }).ignore();
+          saveAttachment({ message, attachment });
           break;
         }
 
diff --git a/ts/models/conversation.ts b/ts/models/conversation.ts
index 6605209e3..a2619d3f5 100644
--- a/ts/models/conversation.ts
+++ b/ts/models/conversation.ts
@@ -422,7 +422,7 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
     if (!registeredMessage || !registeredMessage.message) {
       return null;
     }
-    const model = registeredMessage.message as MessageModel;
+    const model = registeredMessage.message;
     await model.setIsPublic(true);
     await model.setServerId(serverId);
     await model.setServerTimestamp(serverTimestamp);
@@ -1298,7 +1298,10 @@ export class ConversationModel extends Backbone.Model<ConversationAttributes> {
     }
   }
   public async setSubscriberCount(count: number) {
-    this.set({ subscriberCount: count });
+    if (this.get('subscriberCount') !== count) {
+      this.set({ subscriberCount: count });
+      await this.commit();
+    }
     // Not sure if we care about updating the database
   }
   public async setGroupNameAndAvatar(name: any, avatarPath: any) {
diff --git a/ts/receiver/queuedJob.ts b/ts/receiver/queuedJob.ts
index a30d2f264..88152bf76 100644
--- a/ts/receiver/queuedJob.ts
+++ b/ts/receiver/queuedJob.ts
@@ -115,7 +115,7 @@ async function copyFromQuotedMessage(
         window.log.info(
           `Looking for the message id : ${id}, attempt: ${attemptCount + 1}`
         );
-        copyFromQuotedMessage(msg, quote, attemptCount + 1).ignore();
+        void copyFromQuotedMessage(msg, quote, attemptCount + 1);
       }, attemptCount * attemptCount * 500);
     } else {
       window.log.warn(
diff --git a/ts/receiver/receiver.ts b/ts/receiver/receiver.ts
index e4fc39803..3524477b7 100644
--- a/ts/receiver/receiver.ts
+++ b/ts/receiver/receiver.ts
@@ -52,7 +52,7 @@ class EnvelopeQueue {
   // Last pending promise
   private pending: Promise<any> = Promise.resolve();
 
-  public async add(task: any): Promise<any> {
+  public add(task: any): void {
     this.count += 1;
     const promise = this.pending.then(task, task);
     this.pending = promise;
@@ -85,16 +85,16 @@ function queueEnvelope(envelope: EnvelopePlus) {
     `queueEnvelope ${id}`
   );
 
-  const promise = envelopeQueue.add(taskWithTimeout);
-
-  promise.catch((error: any) => {
+  try {
+    envelopeQueue.add(taskWithTimeout);
+  } catch (error) {
     window.log.error(
       'queueEnvelope error handling envelope',
       id,
       ':',
       error && error.stack ? error.stack : error
     );
-  });
+  }
 }
 
 async function handleRequestDetail(
@@ -154,10 +154,7 @@ async function handleRequestDetail(
   }
 }
 
-export async function handleRequest(
-  body: any,
-  options: ReqOptions
-): Promise<void> {
+export function handleRequest(body: any, options: ReqOptions): void {
   // tslint:disable-next-line no-promise-as-boolean
   const lastPromise = _.last(incomingMessagePromises) || Promise.resolve();
 
@@ -210,7 +207,7 @@ async function queueCached(item: any) {
     if (decrypted) {
       const payloadPlaintext = StringUtils.encode(decrypted, 'base64');
 
-      await queueDecryptedEnvelope(envelope, payloadPlaintext);
+      queueDecryptedEnvelope(envelope, payloadPlaintext);
     } else {
       queueEnvelope(envelope);
     }
@@ -236,7 +233,7 @@ async function queueCached(item: any) {
   }
 }
 
-async function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) {
+function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) {
   const id = getEnvelopeId(envelope);
   window.log.info('queueing decrypted envelope', id);
 
@@ -245,14 +242,14 @@ async function queueDecryptedEnvelope(envelope: any, plaintext: ArrayBuffer) {
     task,
     `queueEncryptedEnvelope ${id}`
   );
-  const promise = envelopeQueue.add(taskWithTimeout);
-
-  return promise.catch(error => {
+  try {
+    envelopeQueue.add(taskWithTimeout);
+  } catch (error) {
     window.log.error(
       `queueDecryptedEnvelope error handling envelope ${id}:`,
       error && error.stack ? error.stack : error
     );
-  });
+  }
 }
 
 async function handleDecryptedEnvelope(
diff --git a/ts/session/group/index.ts b/ts/session/group/index.ts
index 80bc58282..cb9a6e1e9 100644
--- a/ts/session/group/index.ts
+++ b/ts/session/group/index.ts
@@ -310,9 +310,7 @@ export async function updateOrCreateClosedGroup(details: GroupInfo) {
 }
 
 export async function leaveClosedGroup(groupId: string) {
-  const convo = ConversationController.getInstance().get(
-    groupId
-  ) as ConversationModel;
+  const convo = ConversationController.getInstance().get(groupId);
 
   if (!convo) {
     window.log.error('Cannot leave non-existing group');
@@ -334,7 +332,9 @@ export async function leaveClosedGroup(groupId: string) {
   } else {
     // otherwise, just the exclude ourself from the members and trigger an update with this
     convo.set({ left: true });
-    members = (convo.get('members') || []).filter(m => m !== ourNumber.key);
+    members = (convo.get('members') || []).filter(
+      (m: string) => m !== ourNumber.key
+    );
     admins = convo.get('groupAdmins') || [];
   }
   convo.set({ members });
diff --git a/ts/session/snode_api/swarmPolling.ts b/ts/session/snode_api/swarmPolling.ts
index e5d32edf9..5ae433956 100644
--- a/ts/session/snode_api/swarmPolling.ts
+++ b/ts/session/snode_api/swarmPolling.ts
@@ -52,7 +52,7 @@ export class SwarmPolling {
     this.lastHashes = {};
   }
 
-  public async start(): Promise<void> {
+  public start(): void {
     this.loadGroupIds();
     void this.pollForAllKeys();
   }
diff --git a/ts/test/session/integration/common.ts b/ts/test/session/integration/common.ts
index 0772ddfe8..0bb5e1d23 100644
--- a/ts/test/session/integration/common.ts
+++ b/ts/test/session/integration/common.ts
@@ -1,6 +1,6 @@
 // tslint:disable: no-implicit-dependencies
 
-import { Application, SpectronClient } from 'spectron';
+import { Application } from 'spectron';
 import path from 'path';
 import url from 'url';
 import http from 'http';
@@ -73,7 +73,7 @@ export class Common {
   }
 
   public static async closeToast(app: Application) {
-    app.client.element(CommonPage.toastCloseButton).click();
+    await app.client.element(CommonPage.toastCloseButton).click();
   }
 
   // a wrapper to work around electron/spectron bug
@@ -219,7 +219,7 @@ export class Common {
     env?: string;
   }) {
     const app = await Common.startAndAssureCleanedApp(env);
-    await Common.startStubSnodeServer();
+    Common.startStubSnodeServer();
 
     if (recoveryPhrase && displayName) {
       await Common.restoreFromRecoveryPhrase(app, recoveryPhrase, displayName);
@@ -562,7 +562,7 @@ export class Common {
     return `Test message from integration tests ${Date.now()}`;
   }
 
-  public static async startStubSnodeServer() {
+  public static startStubSnodeServer() {
     if (!Common.stubSnode) {
       Common.messages = {};
       Common.stubSnode = http.createServer((request: any, response: any) => {
@@ -684,7 +684,7 @@ export class Common {
 
   public static async stopStubSnodeServer() {
     if (Common.stubSnode) {
-      Common.stubSnode.close();
+      await Common.stubSnode.close();
       Common.stubSnode = null;
     }
   }
@@ -695,7 +695,7 @@ export class Common {
    * @param str the string to search (not regex)
    * Note: getRenderProcessLogs() clears the app logs each calls.
    */
-  public static async logsContains(
+  public static logsContains(
     renderLogs: Array<{ message: string }>,
     str: string,
     count?: number
diff --git a/ts/test/session/unit/crypto/MessageEncrypter_test.ts b/ts/test/session/unit/crypto/MessageEncrypter_test.ts
index c05dfb4b0..a3fcbc011 100644
--- a/ts/test/session/unit/crypto/MessageEncrypter_test.ts
+++ b/ts/test/session/unit/crypto/MessageEncrypter_test.ts
@@ -165,9 +165,9 @@ describe('MessageEncrypter', () => {
           .to.deep.equal(SignalService.Envelope.Type.UNIDENTIFIED_SENDER);
       });
 
-      it('should throw an error for anything else than Fallback or ClosedGroup', async () => {
+      it('should throw an error for anything else than Fallback or ClosedGroup', () => {
         const data = crypto.randomBytes(10);
-        await expect(
+        expect(
           MessageEncrypter.encrypt(
             TestUtils.generateFakePubKey(),
             data,
@@ -182,7 +182,7 @@ describe('MessageEncrypter', () => {
   describe('Session Protocol', () => {
     let sandboxSessionProtocol: sinon.SinonSandbox;
 
-    beforeEach(async () => {
+    beforeEach(() => {
       sandboxSessionProtocol = sinon.createSandbox();
 
       sandboxSessionProtocol
diff --git a/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts b/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts
index 560b21c94..ca8224b26 100644
--- a/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts
+++ b/ts/test/session/unit/receiving/ClosedGroupUpdates_test.ts
@@ -1,22 +1,11 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
+
 import chai from 'chai';
-import * as sinon from 'sinon';
 import _ from 'lodash';
 import { describe } from 'mocha';
 
-import { GroupUtils, PromiseUtils, UserUtils } from '../../../../session/utils';
-import { TestUtils } from '../../../../test/test-utils';
-import {
-  generateEnvelopePlusClosedGroup,
-  generateGroupUpdateNameChange,
-} from '../../../test-utils/utils/envelope';
-import { handleClosedGroupControlMessage } from '../../../../receiver/closedGroups';
-import { ConversationController } from '../../../../session/conversations';
-
-// tslint:disable-next-line: no-require-imports no-var-requires no-implicit-dependencies
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
-
-const { expect } = chai;
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 // tslint:disable-next-line: max-func-body-length
 describe('ClosedGroupUpdates', () => {
diff --git a/ts/test/session/unit/sending/MessageQueue_test.ts b/ts/test/session/unit/sending/MessageQueue_test.ts
index a7b5e4a85..6dd33aa27 100644
--- a/ts/test/session/unit/sending/MessageQueue_test.ts
+++ b/ts/test/session/unit/sending/MessageQueue_test.ts
@@ -1,3 +1,5 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
+
 import chai from 'chai';
 import * as sinon from 'sinon';
 import _ from 'lodash';
@@ -15,9 +17,8 @@ import { MessageSender } from '../../../../session/sending';
 import { PendingMessageCacheStub } from '../../../test-utils/stubs';
 import { ClosedGroupMessage } from '../../../../session/messages/outgoing/content/data/group/ClosedGroupMessage';
 
-// tslint:disable-next-line: no-require-imports no-var-requires
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 const { expect } = chai;
 
@@ -35,7 +36,7 @@ describe('MessageQueue', () => {
   // Message Sender Stubs
   let sendStub: sinon.SinonStub<[RawMessage, (number | undefined)?]>;
 
-  beforeEach(async () => {
+  beforeEach(() => {
     // Utils Stubs
     sandbox.stub(UserUtils, 'getOurPubKeyStrFromCache').returns(ourNumber);
 
@@ -65,7 +66,8 @@ describe('MessageQueue', () => {
         messageQueueStub.events.once('sendSuccess', done);
       });
       await messageQueueStub.processPending(device);
-      await expect(successPromise).to.be.fulfilled;
+      // tslint:disable-next-line: no-unused-expression
+      expect(successPromise).to.eventually.be.fulfilled;
     });
 
     it('should remove message from cache', async () => {
@@ -88,7 +90,7 @@ describe('MessageQueue', () => {
           const messages = await pendingMessageCache.getForDevice(device);
           return messages.length === 0;
         });
-        await expect(promise).to.be.fulfilled;
+        return promise.should.be.fulfilled;
       }
     }).timeout(15000);
 
@@ -105,7 +107,6 @@ describe('MessageQueue', () => {
         });
 
         await messageQueueStub.processPending(device);
-        await expect(eventPromise).to.be.fulfilled;
 
         const rawMessage = await eventPromise;
         expect(rawMessage.identifier).to.equal(message.identifier);
@@ -130,7 +131,6 @@ describe('MessageQueue', () => {
         });
 
         await messageQueueStub.processPending(device);
-        await expect(eventPromise).to.be.fulfilled;
 
         const [rawMessage, error] = await eventPromise;
         expect(rawMessage.identifier).to.equal(message.identifier);
@@ -166,7 +166,7 @@ describe('MessageQueue', () => {
   });
 
   describe('sendToGroup', () => {
-    it('should throw an error if invalid non-group message was passed', async () => {
+    it('should throw an error if invalid non-group message was passed', () => {
       // const chatMessage = TestUtils.generateChatMessage();
       // await expect(
       //   messageQueueStub.sendToGroup(chatMessage)
@@ -174,7 +174,7 @@ describe('MessageQueue', () => {
       // Cannot happen with typescript as this function only accept group message now
     });
 
-    describe('closed groups', async () => {
+    describe('closed groups', () => {
       it('can send to closed group', async () => {
         const members = TestUtils.generateFakePubKeys(4).map(
           p => new PubKey(p.key)
@@ -194,7 +194,7 @@ describe('MessageQueue', () => {
         );
       });
 
-      describe('open groups', async () => {
+      describe('open groups', () => {
         let sendToOpenGroupStub: sinon.SinonStub<
           [OpenGroupMessage],
           Promise<{ serverId: number; serverTimestamp: number }>
@@ -223,7 +223,7 @@ describe('MessageQueue', () => {
           }, 2000);
 
           await messageQueueStub.sendToGroup(message);
-          await expect(eventPromise).to.be.fulfilled;
+          return eventPromise.should.be.fulfilled;
         });
 
         it('should emit a fail event if something went wrong', async () => {
@@ -234,7 +234,7 @@ describe('MessageQueue', () => {
           }, 2000);
 
           await messageQueueStub.sendToGroup(message);
-          await expect(eventPromise).to.be.fulfilled;
+          return eventPromise.should.be.fulfilled;
         });
       });
     });
diff --git a/ts/test/session/unit/sending/PendingMessageCache_test.ts b/ts/test/session/unit/sending/PendingMessageCache_test.ts
index 7e493b33d..d3cc81f17 100644
--- a/ts/test/session/unit/sending/PendingMessageCache_test.ts
+++ b/ts/test/session/unit/sending/PendingMessageCache_test.ts
@@ -1,3 +1,4 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
 import { expect } from 'chai';
 import * as sinon from 'sinon';
 import * as _ from 'lodash';
@@ -17,7 +18,7 @@ describe('PendingMessageCache', () => {
   let data: StorageItem;
   let pendingMessageCacheStub: PendingMessageCache;
 
-  beforeEach(async () => {
+  beforeEach(() => {
     // Stub out methods which touch the database
     const storageID = 'pendingMessages';
     data = {
diff --git a/ts/test/session/unit/utils/JobQueue_test.ts b/ts/test/session/unit/utils/JobQueue_test.ts
index 1abb38b87..ecdc6e7fe 100644
--- a/ts/test/session/unit/utils/JobQueue_test.ts
+++ b/ts/test/session/unit/utils/JobQueue_test.ts
@@ -1,11 +1,12 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
+
 import chai from 'chai';
 import { v4 as uuid } from 'uuid';
 import { JobQueue } from '../../../../session/utils/JobQueue';
 import { TestUtils } from '../../../test-utils';
 
-// tslint:disable-next-line: no-require-imports no-var-requires
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 const { assert } = chai;
 
diff --git a/ts/test/session/unit/utils/Messages_test.ts b/ts/test/session/unit/utils/Messages_test.ts
index 57aaa699e..d34e217bb 100644
--- a/ts/test/session/unit/utils/Messages_test.ts
+++ b/ts/test/session/unit/utils/Messages_test.ts
@@ -17,9 +17,9 @@ import {
 import { MockConversation } from '../../../test-utils/utils';
 import { ConfigurationMessage } from '../../../../session/messages/outgoing/content/ConfigurationMessage';
 import { ConversationModel } from '../../../../models/conversation';
-// tslint:disable-next-line: no-require-imports no-var-requires
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
+
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 const { expect } = chai;
 
diff --git a/ts/test/session/unit/utils/Promise_test.ts b/ts/test/session/unit/utils/Promise_test.ts
index 28ec57532..1bc04261c 100644
--- a/ts/test/session/unit/utils/Promise_test.ts
+++ b/ts/test/session/unit/utils/Promise_test.ts
@@ -1,11 +1,13 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
+
 import chai from 'chai';
 import * as sinon from 'sinon';
 
 import { PromiseUtils } from '../../../../session/utils';
 
 // tslint:disable-next-line: no-require-imports no-var-requires
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 const { expect } = chai;
 
@@ -49,20 +51,20 @@ describe('Promise Utils', () => {
       };
 
       const promise = PromiseUtils.poll(task, {});
+      await promise;
 
-      await expect(promise).to.be.fulfilled;
       expect(pollSpy.callCount).to.equal(1);
       expect(completionSpy.callCount).to.equal(1);
     });
 
-    it('can timeout a task', async () => {
+    it('can timeout a task', () => {
       // completionSpy will be called on done
       const completionSpy = sandbox.spy();
       const task = (_done: any) => undefined;
 
       const promise = PromiseUtils.poll(task, { timeoutMs: 1 });
 
-      await expect(promise).to.be.rejectedWith('Periodic check timeout');
+      promise.should.eventually.be.rejectedWith('Periodic check timeout');
       expect(pollSpy.callCount).to.equal(1);
       expect(completionSpy.callCount).to.equal(0);
     });
@@ -83,8 +85,8 @@ describe('Promise Utils', () => {
       };
 
       const promise = PromiseUtils.poll(task, { timeoutMs: timeout, interval });
+      await promise;
 
-      await expect(promise).to.be.fulfilled;
       expect(pollSpy.callCount).to.equal(1);
       expect(recurrenceSpy.callCount).to.equal(expectedRecurrences);
     });
@@ -103,19 +105,19 @@ describe('Promise Utils', () => {
 
       const promise = PromiseUtils.waitForTask(task);
 
-      await expect(promise).to.be.fulfilled;
+      await promise;
       expect(waitForTaskSpy.callCount).to.equal(1);
       expect(completionSpy.callCount).to.equal(1);
     });
 
-    it('can timeout a task', async () => {
+    it('can timeout a task', () => {
       // completionSpy will be called on done
       const completionSpy = sandbox.spy();
       const task = async (_done: any) => undefined;
 
       const promise = PromiseUtils.waitForTask(task, 1);
 
-      await expect(promise).to.be.rejectedWith('Task timed out.');
+      promise.should.eventually.be.rejectedWith('Task timed out.');
       expect(waitForTaskSpy.callCount).to.equal(1);
       expect(completionSpy.callCount).to.equal(0);
     });
@@ -125,16 +127,16 @@ describe('Promise Utils', () => {
     it('can wait for check', async () => {
       const check = () => true;
       const promise = PromiseUtils.waitUntil(check);
+      await promise;
 
-      await expect(promise).to.be.fulfilled;
       expect(waitUntilSpy.callCount).to.equal(1);
     });
 
-    it('can timeout a check', async () => {
+    it('can timeout a check', () => {
       const check = () => false;
       const promise = PromiseUtils.waitUntil(check, 1);
 
-      await expect(promise).to.be.rejectedWith('Periodic check timeout');
+      promise.should.eventually.be.rejectedWith('Periodic check timeout');
       expect(waitUntilSpy.callCount).to.equal(1);
     });
   });
diff --git a/ts/test/session/unit/utils/String_test.ts b/ts/test/session/unit/utils/String_test.ts
index 5e42bf731..503a9023b 100644
--- a/ts/test/session/unit/utils/String_test.ts
+++ b/ts/test/session/unit/utils/String_test.ts
@@ -1,3 +1,4 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
 import chai from 'chai';
 import ByteBuffer from 'bytebuffer';
 
@@ -5,15 +6,14 @@ import ByteBuffer from 'bytebuffer';
 import { Encoding } from '../../../../session/utils/String';
 import { StringUtils } from '../../../../session/utils';
 
-// tslint:disable-next-line: no-require-imports no-var-requires
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 const { expect } = chai;
 
 describe('String Utils', () => {
   describe('encode', () => {
-    it('can encode to base64', async () => {
+    it('can encode to base64', () => {
       const testString = 'AAAAAAAAAA';
       const encoded = StringUtils.encode(testString, 'base64');
 
@@ -24,7 +24,7 @@ describe('String Utils', () => {
       expect(encoded.byteLength).to.be.greaterThan(0);
     });
 
-    it('can encode to hex', async () => {
+    it('can encode to hex', () => {
       const testString = 'AAAAAAAAAA';
       const encoded = StringUtils.encode(testString, 'hex');
 
@@ -35,14 +35,14 @@ describe('String Utils', () => {
       expect(encoded.byteLength).to.be.greaterThan(0);
     });
 
-    it('wont encode invalid hex', async () => {
+    it('wont encode invalid hex', () => {
       const testString = 'ZZZZZZZZZZ';
       const encoded = StringUtils.encode(testString, 'hex');
 
       expect(encoded.byteLength).to.equal(0);
     });
 
-    it('can encode to binary', async () => {
+    it('can encode to binary', () => {
       const testString = 'AAAAAAAAAA';
       const encoded = StringUtils.encode(testString, 'binary');
 
@@ -53,7 +53,7 @@ describe('String Utils', () => {
       expect(encoded.byteLength).to.be.greaterThan(0);
     });
 
-    it('can encode to utf8', async () => {
+    it('can encode to utf8', () => {
       const testString = 'AAAAAAAAAA';
       const encoded = StringUtils.encode(testString, 'binary');
 
@@ -64,7 +64,7 @@ describe('String Utils', () => {
       expect(encoded.byteLength).to.be.greaterThan(0);
     });
 
-    it('can encode empty string', async () => {
+    it('can encode empty string', () => {
       const testString = '';
       expect(testString).to.have.length(0);
 
@@ -81,7 +81,7 @@ describe('String Utils', () => {
       });
     });
 
-    it('can encode huge string', async () => {
+    it('can encode huge string', () => {
       const stringSize = Math.pow(2, 16);
       const testString = Array(stringSize)
         .fill('0')
@@ -100,7 +100,7 @@ describe('String Utils', () => {
       });
     });
 
-    it("won't encode illegal string length in hex", async () => {
+    it("won't encode illegal string length in hex", () => {
       const testString = 'A';
       const encode = () => StringUtils.encode(testString, 'hex');
 
@@ -109,7 +109,7 @@ describe('String Utils', () => {
       expect(encode).to.throw('Illegal str: Length not a multiple of 2');
     });
 
-    it('can encode obscure string', async () => {
+    it('can encode obscure string', () => {
       const testString =
         '↓←¶ᶑᵶ⅑⏕→⅓‎ᵹ⅙ᵰᶎ⅔⅗↔‌ᶈ⅞⸜ᶊᵴᶉ↉¥ᶖᶋᶃᶓ⏦ᵾᶂᶆ↕⸝ᶔᶐ⏔£⏙⅐⅒ᶌ⁁ᶘᶄᶒᶸ⅘‏⅚⅛ᶙᶇᶕᶀ↑ᵿ⏠ᶍᵯ⏖⏗⅜ᶚᶏ⁊‍ᶁᶗᵽᵼ⅝⏘⅖⅕⏡';
 
@@ -128,7 +128,7 @@ describe('String Utils', () => {
   });
 
   describe('decode', () => {
-    it('can decode empty buffer', async () => {
+    it('can decode empty buffer', () => {
       const buffer = new ByteBuffer(0);
 
       const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
@@ -143,7 +143,7 @@ describe('String Utils', () => {
       });
     });
 
-    it('can decode huge buffer', async () => {
+    it('can decode huge buffer', () => {
       const bytes = Math.pow(2, 16);
       const bufferString = Array(bytes)
         .fill('A')
@@ -162,7 +162,7 @@ describe('String Utils', () => {
       });
     });
 
-    it('can decode from ByteBuffer', async () => {
+    it('can decode from ByteBuffer', () => {
       const buffer = ByteBuffer.fromUTF8('AAAAAAAAAA');
 
       const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
@@ -177,7 +177,7 @@ describe('String Utils', () => {
       });
     });
 
-    it('can decode from Buffer', async () => {
+    it('can decode from Buffer', () => {
       const arrayBuffer = new ArrayBuffer(10);
       const buffer = Buffer.from(arrayBuffer);
       buffer.writeUInt8(0, 0);
@@ -194,7 +194,7 @@ describe('String Utils', () => {
       });
     });
 
-    it('can decode from ArrayBuffer', async () => {
+    it('can decode from ArrayBuffer', () => {
       const buffer = new ArrayBuffer(10);
 
       const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
@@ -209,7 +209,7 @@ describe('String Utils', () => {
       });
     });
 
-    it('can decode from Uint8Array', async () => {
+    it('can decode from Uint8Array', () => {
       const buffer = new Uint8Array(10);
 
       const encodings = ['base64', 'hex', 'binary', 'utf8'] as Array<Encoding>;
diff --git a/ts/test/session/unit/utils/SyncUtils_test.ts b/ts/test/session/unit/utils/SyncUtils_test.ts
index d3c951775..a5594b807 100644
--- a/ts/test/session/unit/utils/SyncUtils_test.ts
+++ b/ts/test/session/unit/utils/SyncUtils_test.ts
@@ -1,15 +1,10 @@
+// tslint:disable: no-implicit-dependencies
 import chai from 'chai';
 import * as sinon from 'sinon';
-import { ConversationController } from '../../../../session/conversations';
-import * as MessageUtils from '../../../../session/utils/Messages';
-import { syncConfigurationIfNeeded } from '../../../../session/utils/syncUtils';
-import { TestUtils } from '../../../test-utils';
 import { restoreStubs } from '../../../test-utils/utils';
-// tslint:disable-next-line: no-require-imports no-var-requires
-const chaiAsPromised = require('chai-as-promised');
-chai.use(chaiAsPromised);
 
-const { expect } = chai;
+import chaiAsPromised from 'chai-as-promised';
+chai.use(chaiAsPromised as any);
 
 describe('SyncUtils', () => {
   const sandbox = sinon.createSandbox();
@@ -20,7 +15,7 @@ describe('SyncUtils', () => {
   });
 
   describe('syncConfigurationIfNeeded', () => {
-    it('sync if last sync undefined', async () => {
+    it('sync if last sync undefined', () => {
       // TestUtils.stubData('getItemById').resolves(undefined);
       // sandbox.stub(ConversationController.getInstance(), 'getConversations').returns([]);
       // const getCurrentConfigurationMessageSpy = sandbox.spy(MessageUtils, 'getCurrentConfigurationMessage');
diff --git a/ts/test/tslint.json b/ts/test/tslint.json
index d18bab561..ebe01b7f1 100644
--- a/ts/test/tslint.json
+++ b/ts/test/tslint.json
@@ -2,15 +2,10 @@
   "defaultSeverity": "error",
   "extends": ["../../tslint.json"],
   "rules": {
-    // To allow the use of devDependencies here
     "no-implicit-dependencies": false,
-
-    // All tests use arrow functions, and they can be long
     "max-func-body-length": false,
-
     "no-unused-expression": false,
     "no-unused-variable": false,
-
     "await-promise": [true, "PromiseLike"],
     "no-floating-promises": [true, "PromiseLike"]
   }
diff --git a/ts/test/util/blockedNumberController_test.ts b/ts/test/util/blockedNumberController_test.ts
index 83a7302ba..f4d3dee3f 100644
--- a/ts/test/util/blockedNumberController_test.ts
+++ b/ts/test/util/blockedNumberController_test.ts
@@ -1,3 +1,5 @@
+// tslint:disable: no-implicit-dependencies max-func-body-length no-unused-expression
+
 import { expect } from 'chai';
 import * as sinon from 'sinon';
 import { BlockedNumberController } from '../../util/blockedNumberController';
@@ -35,7 +37,7 @@ describe('BlockedNumberController', () => {
     TestUtils.restoreStubs();
   });
 
-  describe('load', async () => {
+  describe('load', () => {
     it('should load data from the database', async () => {
       const normal = TestUtils.generateFakePubKey();
       const group = TestUtils.generateFakePubKey();
@@ -62,7 +64,7 @@ describe('BlockedNumberController', () => {
     });
   });
 
-  describe('block', async () => {
+  describe('block', () => {
     it('should block the user', async () => {
       const other = TestUtils.generateFakePubKey();
 
@@ -76,7 +78,7 @@ describe('BlockedNumberController', () => {
     });
   });
 
-  describe('unblock', async () => {
+  describe('unblock', () => {
     it('should unblock the user', async () => {
       const primary = TestUtils.generateFakePubKey();
       memoryDB.blocked = [primary.key];
@@ -103,7 +105,7 @@ describe('BlockedNumberController', () => {
     });
   });
 
-  describe('blockGroup', async () => {
+  describe('blockGroup', () => {
     it('should block a group', async () => {
       const group = TestUtils.generateFakePubKey();
 
@@ -118,7 +120,7 @@ describe('BlockedNumberController', () => {
     });
   });
 
-  describe('unblockGroup', async () => {
+  describe('unblockGroup', () => {
     it('should unblock a group', async () => {
       const group = TestUtils.generateFakePubKey();
       const another = TestUtils.generateFakePubKey();
@@ -134,7 +136,7 @@ describe('BlockedNumberController', () => {
     });
   });
 
-  describe('isBlocked', async () => {
+  describe('isBlocked', () => {
     it('should return true if number is blocked', async () => {
       const pubKey = TestUtils.generateFakePubKey();
       const groupPubKey = TestUtils.generateFakePubKey();
@@ -198,7 +200,7 @@ describe('BlockedNumberController', () => {
     });
   });
 
-  describe('isGroupBlocked', async () => {
+  describe('isGroupBlocked', () => {
     it('should return true if group is blocked', async () => {
       const pubKey = TestUtils.generateFakePubKey();
       const groupPubKey = TestUtils.generateFakePubKey();
diff --git a/tslint.json b/tslint.json
index 70bd8cdd7..9b974cd23 100644
--- a/tslint.json
+++ b/tslint.json
@@ -7,40 +7,31 @@
     "align": false,
     "newline-per-chained-call": false,
     "array-type": [true, "generic"],
-
     // Preferred by Prettier:
     "arrow-parens": [true, "ban-single-arg-parens"],
-
     "import-spacing": false,
     "indent": [true, "spaces", 2],
     "interface-name": [true, "never-prefix"],
-
     // Allows us to write inline `style`s. Revisit when we have a more sophisticated
     // CSS-in-JS solution:
     "jsx-no-multiline-js": false,
-
     // We'll make tradeoffs where appropriate
     "jsx-no-lambda": false,
     "react-this-binding-issue": false,
-
     "linebreak-style": [true, "LF"],
-
     // Prettier handles this for us
     "max-line-length": false,
-
     "mocha-avoid-only": true,
     // Disabled until we can allow dynamically generated tests:
     // https://github.com/Microsoft/tslint-microsoft-contrib/issues/85#issuecomment-371749352
     "mocha-no-side-effect-code": false,
     "mocha-unneeded-done": true,
-
     // We always want 'as Type'
     "no-angle-bracket-type-assertion": true,
-
     "no-consecutive-blank-lines": [true, 2],
     "object-literal-key-quotes": [true, "as-needed"],
     "object-literal-sort-keys": false,
-
+    "no-async-without-await": true,
     // Ignore import sources order until we can specify that we want ordering
     // based on import name vs module name:
     "ordered-imports": [
@@ -50,7 +41,6 @@
         "named-imports-order": "case-insensitive"
       }
     ],
-
     "quotemark": [
       true,
       "single",
@@ -58,10 +48,8 @@
       "avoid-template",
       "avoid-escape"
     ],
-
     // Preferred by Prettier:
     "semicolon": [true, "always", "ignore-bound-class-methods"],
-
     // Preferred by Prettier:
     "trailing-comma": [
       true,
@@ -76,11 +64,8 @@
         "esSpecCompliant": true
       }
     ],
-
     // Disabling a large set of Microsoft-recommended rules
-
     // Modifying:
-
     // React components and namespaces are Pascal case
     "variable-name": [
       true,
@@ -88,7 +73,6 @@
       "allow-leading-underscore",
       "allow-pascal-case"
     ],
-
     "function-name": [
       true,
       {
@@ -99,12 +83,9 @@
         "static-method-regex": "^[a-zA-Z][\\w\\d]+$"
       }
     ],
-
     // Adding select dev dependencies here for now, may turn on all in the future
     "no-implicit-dependencies": [true, ["dashdash", "electron"]],
-
     // Maybe will turn on:
-
     // We're not trying to be comprehensive with JSDoc right now. We have the style guide.
     "completed-docs": false,
     // Today we have files with a single named export which isn't the filename. Eventually.
@@ -121,9 +102,7 @@
     "no-unsafe-any": false,
     // Not everything needs to be typed right now
     "typedef": false,
-
     // Probably won't turn on:
-
     "possible-timing-attack": false,
     // We use null
     "no-null-keyword": false,