Nonprofit Success Pack Account Model and Introduction to TDTM

I have been working on npsp (nonprofit success pack) since it was launched and was called (nonprofit starter pack) that time. It has been an amazing product for nonprofits and I don’t want to miss on including the product tagline “A product build by nonprofits, for nonprofits”. This blog “Nonprofit Success Pack Account Model and Introduction to TDTM” is inclined to share some basic insights about the account/data model of npsp as a Salesforce product and concept of TDTM (Table driven trigger management). Hope this blog help you understand npsp to the core and also provide you with some resources to go-through.

The Nonprofit Success Pack is an easy-to-use fundraising and constituent management application on the Salesforce platform. A free and open-source application from, NPSP harnesses the power of Salesforce’s vibrant nonprofit community. 


  1. Easily and effectively manage users, donors, contacts, volunteers, and more. Track Households and connections between your organization’s critical constituents.
  2. Track donations, pledges, recurring and planned giving, hard and soft credits, and much, much more. Reconcile general allocation units (GAU), cash, and revenue across your entire organization.
  3. Highly configurable and customizable, the Nonprofit Success Pack not only serves as a great donor management system right out of the box, but can evolve as your organization and its needs do the same.

NPSP Account Model

There are two main types of accounts you can create in NPSP: Households and organizations. Household accounts are used to track donor or member households. Organization accounts are used for any other accounts such as funders, corporate donors, vendors, government institutions, or other business entities.

The NPSP data model also includes objects custom to NPSP including affiliations, relationships, engagement plan templates, recurring donations, payments etc

This is how the NPSP data model looks like:

Image source: Trailhead

Introduction to Table-Driven Trigger Management (TDTM) in NPSP

It is the Nonprofit Success pack’s approach to trigger management. As you probably know, large custom applications or packages, such as the NPSP, can often wind up with a large number of triggers, including multiple triggers/automated processes on the same object (a very bad practice). These multiple triggers are often written by different developers and even consulting companies, and can interact with each other in sometimes-unpredictable ways. Under these circumstances, problems become very hard to understand, and even harder to debug. TDTM makes it easier for us and for our users to know what happens when a user interacts with a record.

TDTM has several uses. TDTM lets you:

  1. Disable specific pieces of code
  2. Build your own custom code that works in conjunction with NPSP
  3. Control the order in which the code executes


In TDTM design, only one trigger exists for each object (one for Contact, one for Account, one for Opportunity, and so on), both for standard and for custom objects. We created a custom  object, Trigger_Handler__c, to store which classes should run for each object, along with the related actions. In this object we also define whether the class is active or inactive, and whether the logic is going to be run synchronously or asynchronously. The Trigger Handler is then charged with the task of calling these classes when appropriate, which provides the added advantage of allowing us to centralize error handling for triggers around the Trigger Handler.

That leaves us with the following fields in our Trigger_Handler__c custom object:

  • – Class__c: the class to run
  • – Object__c: the object that, when being modified, will make the class run
  • – Trigger_Action__c: the actions on which the class will run (before insert, after update, and so on)
  • – Load_Order__c: the order in which classes for the same object, and with the same actions, will run
  • – Asynchronous__c: a flag that specifies whether the class will run synchronously or asynchronously

This is extensible as well. If you need to create a new class and want to include that apex class in the TDTM architecture, click New Trigger Handler to add a Trigger Handler for that class.

Disable Trigger Handlers:

For custom code, a large data import, or an external integration to run successfully, you might need to permanently or temporarily disable TDTM Trigger Handlers. For example, you can disable a Trigger Handler to:

  1. Temporarily disable certain Apex classes when inserting a large volume of records with data that is already structured in its final format.
  2. Disable Address-related Apex code when inserting or updating Contacts through a scheduled ETL job that always runs as a specific User.
  3. Temporarily prevent Payment or Opportunity Contact Role records from being created when Opportunities are inserted through a third-party package from the AppExchange.

In these situations, disabling Trigger Handlers is easy to do. No code is necessary.

Uncheck the Active checkbox to disable a Trigger Handler and the Apex class associated with it.

Look at the below screenshot


Learning Resources:


Hope you find this blog helpful and my experience working on this product has been amazing and hope the same way for you. So “keep blazing npsp trails” and there are many more blogs to follow soon, #HappyLearning