I paid $89 per month for HubSpot CRM before realizing most of my sales team ignored it. The interface felt bloated, the mobile app lagged during client calls, and customizing fields required opening support tickets. When I asked why nobody logged their conversations, the answer was always the same: too many clicks, too slow, doesn't match our workflow.

I rebuilt our entire sales pipeline in Notion over a weekend using database relations. Not templates — actual relational architecture where contacts link to companies, deals reference specific contacts, and activities roll up automatically. Three months in, our pipeline visibility went from 40% to 94% because the system finally matched how my team actually worked.

This isn't a template walkthrough. I'm showing you how to architect the database structure so you understand why each relation exists and how to modify it for your business. You'll build four interconnected databases: Companies, Contacts, Deals, and Activities. By the end, you'll have a CRM that shows deal values automatically calculated from contact relationships, activity timelines that update across all linked records, and pipeline views that actually reflect reality.

Prerequisites

You'll need:

  • A Notion workspace (free plan works fine for this build)
  • Basic familiarity with creating Notion pages and databases
  • Understanding of your sales process (lead stages, typical deal size, how you track client interactions)

The third requirement matters more than you'd think. I tried building a CRM without mapping our actual process first, and ended up with a database full of fields we never used. Spend 15 minutes sketching your pipeline stages and what information you actually need at each stage before touching Notion.

Step-by-Step Guide

Step 1: Build the Companies Database (Your Foundation)

Create a new page in Notion and add a database. Name it "Companies." This is your anchor — every other database will reference back to this one.

Set up these properties:

  • Company Name (Title field) — Keep this clean, no prefixes like "Company:" that bloat your relation dropdowns
  • Industry (Select) — Add your common categories like SaaS, Manufacturing, Healthcare
  • Company Size (Select) — Use ranges: 1-10, 11-50, 51-200, 201-1000, 1000+
  • Website (URL) — Notion automatically makes this clickable
  • Status (Select) — Active, Churned, Prospect
Here's what I learned about the Status field: don't create separate databases for prospects vs. customers. Use one Companies database with a status selector. I initially built "Prospects" and "Customers" as separate databases, then realized prospects become customers. Moving records between databases breaks all your relations. One database with status changes is far cleaner.

Add a few test companies now. You'll need them when setting up relations in the next databases.

Step 2: Create the Contacts Database with Company Relations

Create a second database called "Contacts." This is where individual people live.

Properties:

  • Contact Name (Title)
  • Email (Email property type) — Use Notion's native email type so you can click to compose
  • Phone (Phone number property)
  • Role (Text) — Their job title
  • Company (Relation) — This is the critical connection

Setting up the Company relation properly:

  1. Click "+ Add a property" and select "Relation"
  2. Choose your Companies database from the dropdown
  3. Enable "Show on Companies" — this creates a reciprocal relation so Companies can see their linked contacts
  4. In the configuration panel, name the reverse relation "Contacts" (plural)

The naming matters. When you're in the Companies database looking at a company record, you'll see a property called "Contacts" showing all linked people. When you're in the Contacts database, you'll see "Company" (singular) showing which company that person works for.

Create a few test contacts and link them to your test companies. You should now be able to open a company record and see all associated contacts listed automatically.

Step 3: Build the Deals Database with Multi-Layer Relations

Create a third database: "Deals." This tracks your pipeline opportunities.

Core properties:

  • Deal Name (Title) — I use format: "Company Name - Product/Service"
  • Company (Relation to Companies database)
  • Primary Contact (Relation to Contacts database)
  • Deal Value (Number, formatted as currency)
  • Stage (Select) — Lead, Qualified, Proposal, Negotiation, Closed Won, Closed Lost
  • Probability (Number, formatted as percent)
  • Expected Close Date (Date)

Now add a Rollup property to pull company data into your deals:

  • Add property → Rollup
  • Name it "Company Industry"
  • Relation: Company
  • Property: Industry
  • Calculate: Show original

This automatically displays the company's industry in your deals view without manually copying it. When the company's industry changes, every linked deal updates instantly.

Here's a mistake that cost me hours: I created the Primary Contact relation before linking the deal to a company. When I tried to select a contact, Notion showed every contact in the database (hundreds of them). The fix: always link the Company relation first. Then add a filter to your Primary Contact relation that only shows contacts from the selected company.

To filter the Primary Contact dropdown:
5. Click on the Primary Contact property settings (three dots)
6. Choose "Limit to" under Relation configuration
7. Set filter: Company (in Contacts) → Contains → Company (in Deals)

Now when you select a company for a deal, the Primary Contact dropdown only shows people who work at that company. This single filter prevents 90% of data entry errors.

Step 4: Create the Activities Database (Interaction Tracking)

Fourth database: "Activities." This logs every call, email, and meeting.

Properties:

  • Activity Title (Title) — Auto-generate this with a formula later
  • Type (Select) — Email, Call, Meeting, Demo, Proposal Sent
  • Date (Date with time)
  • Contact (Relation to Contacts)
  • Related Deal (Relation to Deals)
  • Notes (Text, long form)

Now add a rollup to pull the company through the contact relation:

  • Property name: Company
  • Property type: Rollup
  • Relation: Contact
  • Property: Company
  • Calculate: Show original

This is a second-degree relation. You're pulling Company data through the Contact relation. When you log an activity with a specific contact, Notion automatically shows which company that contact belongs to. No manual entry required.

Replace the basic Activity Title with a formula that auto-generates descriptive titles:

prop("Type") + " with " + prop("Contact").replaceAll("(^|, )(.)", "$1$2") + " - " + formatDate(prop("Date"), "MMM D")

This creates titles like "Call with John Smith - Mar 15" automatically. The replaceAll removes any weird formatting from contact names.

Step 5: Add Reverse Rollups to Surface Activity Data

Now the powerful part: making activity data visible in your other databases.

Go back to your Deals database. Add these rollup properties:

Last Activity Date:

  • Rollup from Activities
  • Property: Date
  • Calculate: Latest date

Activity Count:

  • Rollup from Activities
  • Property: Type
  • Calculate: Count values

Now when you look at a deal, you instantly see how many touchpoints you've had and when the last one occurred. This replaced our weekly "which deals have gone cold" meetings entirely.

Add the same rollups to your Companies database:

  • Last Contact Date (rollup from Activities → Date → Latest)
  • Total Interactions (rollup from Activities → Type → Count)
  • Total Deal Value (rollup from Deals → Deal Value → Sum)

The Total Deal Value rollup is particularly useful. It shows the aggregate value of all deals associated with a company, letting you prioritize high-value accounts instantly.

Step 6: Create Filtered Views for Daily Workflow

Database relations are pointless if your views don't surface the right information. Here are the views I use daily:

In Deals database:

  • Pipeline Board — Group by Stage, sort by Expected Close Date, filter out Closed Lost
  • Stale Deals — Table view, filter: Last Activity Date is before 7 days ago AND Stage is not Closed Won/Lost
  • High Value — Table view, filter: Deal Value greater than $10,000, sort descending by value

The Stale Deals view alone recovered $40K in opportunities we'd forgotten about. When you filter by Last Activity Date, you're using the rollup you created in Step 5.

In Companies database:

  • Active Accounts — Filter: Status is Active, sort by Total Deal Value descending
  • At Risk — Filter: Status is Active AND Last Contact Date is before 30 days ago

In Activities database:

  • This Week — Calendar view grouped by Date, filter: Date is within 1 week
  • Upcoming Calls — Table view, filter: Type is Call AND Date is after today, sort by Date ascending

Step 7: Build a Dashboard Page Linking Everything

Create a new page called "Sales Dashboard." This becomes your daily workspace. Add linked databases (not new databases) to this page:

  1. Type "/linked" and select "Create linked database"
  2. Choose your Deals database
  3. Select your "Pipeline Board" view
  4. Repeat for your Stale Deals view
  5. Add your Activities "This Week" calendar view

Now you have one page showing your pipeline, neglected deals, and upcoming activities. Changes made anywhere update everywhere because these are linked databases, not copies.

I added a formula property to the dashboard that calculates weighted pipeline value:

prop("Deal Value") * prop("Probability") / 100

This shows realistic revenue projections instead of pie-in-the-sky totals. A $100K deal at 20% probability contributes $20K to your weighted pipeline.

The "Gotcha" — Circular Relations Will Break Your Database

Two months into using this CRM, I tried to add a "Related Deals" property to my Activities database so I could link one activity to multiple deals. Made sense — sometimes a single call discusses three different opportunities. I created the relation, and immediately every rollup in my Deals database showed "Error: Circular dependency detected."

Here's what happened:
• Activities already had a relation to Deals ("Related Deal")
• Deals had a rollup pulling Last Activity Date from Activities
• When I added the reverse relation (Deals → Activities), it created a loop.

Notion can't calculate rollups through circular references. The fix required restructuring the entire relationship:
13. Delete the rollup properties in Deals that reference Activities
14. Add the bidirectional relation between Deals and Activities
15. Recreate the rollups — they work now because Notion processes the bidirectional relation differently.

Common Errors & How to Fix Them

Error 1: Rollup Shows Empty When Data Exists

Causes: The rollup is pointing to the wrong property; the calculation type doesn't match the property type; or the relation is configured but not actually linked. Fix: Open the rollup settings and verify the Relation field shows the correct database name (case-sensitive). Use "Show original" first to confirm data is flowing.

Error 2: Can't Find Records in Relation Dropdown

This happens when you have database filters or limits applied to the relation. Fix: Click the relation property name at the top of your database, then check for "Limit to" settings. Remove any filters temporarily to see if your record appears.

Error 3: "This Property Cannot Be Edited"

This is expected behavior. Rollups and formulas are computed fields. Fix: Create a new property called "Manual Override." Add a third formula field that checks if the override exists: if(empty(prop("Manual Override")), prop("Calculated Value"), prop("Manual Override")).

Error 4: Relations Break When Renaming Databases

Actually, this doesn't happen in Notion — relations survive renames. But what does break relations is moving a database to a different page, then deleting the original page. Fix: Before restructuring your workspace, duplicate your entire CRM page. Keep the duplicate until you verify the new structure works.

Error 5: Rollup Calculations Show Wrong Totals

Your "Total Deal Value" rollup shows $450K but when you manually add up the deals, it's only $180K. This happens with multi-select relations where a single deal is linked to multiple companies. Fix: Audit your relations. Filter your Deals database to show records where the Company relation count is greater than 1. Enforce proper data entry guidelines.

Conclusion

This CRM structure scales. I started with 30 companies and now track 400+ without performance issues. The relational architecture means adding new fields takes seconds, not the hours of custom development traditional CRMs require.

Start with just Companies and Contacts. Use it for a week. Once that feels natural, add Deals. Then Activities. Building incrementally prevents the overwhelm that kills most Notion projects.

The real power unlocks when you start chaining rollups — pulling company data into deals, then rolling deal metrics back into companies. That's when Notion stops being a note-taking app and starts being actual infrastructure.

For advanced implementations, explore Niskart's guides on Notion API automation and building client portals with filtered database views.