Building a Full-Stack Photography Management System with .NET Core and PostgreSQL
Development

Building a Full-Stack Photography Management System with .NET Core and PostgreSQL

Ricardo Gil
December 30, 2025
7 min read
#.NET Core #PostgreSQL #Angular #Full-Stack #Photography #Business Software

Introduction

Managing a photography business involves juggling clients, bookings, galleries, invoicing, and communication—all while trying to focus on what matters most: taking great photos. After working with several photography businesses, I noticed a common pain point: existing solutions were either too expensive, too complex, or lacked the specific features photographers needed.

That's why I built PhotoManagerAPI, a comprehensive full-stack solution using .NET Core 8, Angular 18, and PostgreSQL. In this post, I'll walk you through the architecture, key features, and technical decisions that make this system both powerful and maintainable.

The Problem: Why Build Custom Software?

Off-the-shelf photography management tools often fall short in several ways:

  • Generic workflows that don't match how photographers actually work
  • High monthly costs that eat into already thin margins
  • Limited customization when business needs change
  • Poor integration with existing tools and workflows
  • Data lock-in making it hard to switch providers

A custom solution addresses these issues while providing exactly the features needed—nothing more, nothing less.

Architecture Overview

The system follows a clean, modern architecture that separates concerns and enables independent scaling:

Backend: .NET Core 8 Web API

The API layer handles all business logic, data access, and security. Here's why .NET Core was the right choice:

  • Performance: Native async/await support and minimal overhead
  • Type safety: Strong typing catches errors at compile time
  • Rich ecosystem: NuGet packages for everything we need
  • Cross-platform: Deploy anywhere—Windows, Linux, or containers
  • Long-term support: Microsoft's commitment to LTS releases

Frontend: Angular 18

Angular provides the structure needed for a complex business application:

  • Component architecture: Reusable, testable UI components
  • TypeScript: Type safety on the frontend too
  • Reactive forms: Complex validation made simple
  • RxJS: Powerful data flow management
  • Signals: The new reactive primitive for better performance

Database: PostgreSQL

PostgreSQL handles all data persistence with excellent performance:

  • ACID compliance: Data integrity is non-negotiable
  • JSON support: Flexible data structures when needed
  • Full-text search: Built-in search without extra tools
  • Advanced indexing: Lightning-fast queries
  • Open source: No licensing costs or vendor lock-in

Core Features

1. Client Management

Track everything about your clients in one place:

csharp
public class Client
{
    public Guid Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public string Email { get; set; }
    public string Phone { get; set; }
    public string Address { get; set; }
    public List<Booking> Bookings { get; set; }
    public List<Invoice> Invoices { get; set; }
    public DateTime CreatedAt { get; set; }
    public DateTime? LastContactedAt { get; set; }
}

The client model includes relationships to bookings and invoices, making it easy to see the complete history at a glance.

2. Booking System

Schedule shoots with conflict detection:

csharp
public async Task<BookingResult> CreateBookingAsync(CreateBookingDto dto)
{
    // Check for scheduling conflicts
    var hasConflict = await _context.Bookings
        .AnyAsync(b => 
            b.PhotographerId == dto.PhotographerId &&
            b.Date == dto.Date &&
            b.Status != BookingStatus.Cancelled);
    
    if (hasConflict)
    {
        return BookingResult.Conflict("Time slot already booked");
    }
    
    var booking = _mapper.Map<Booking>(dto);
    booking.Status = BookingStatus.Pending;
    
    _context.Bookings.Add(booking);
    await _context.SaveChangesAsync();
    
    // Send confirmation email
    await _emailService.SendBookingConfirmationAsync(booking);
    
    return BookingResult.Success(booking);
}

3. Gallery Management

Organize and share photos with clients:

  • Upload to AWS S3: Scalable, reliable storage
  • Image optimization: Automatic thumbnails and compression
  • Access control: Client-specific gallery passwords
  • Bulk operations: Upload, download, delete in batches
  • Expiration dates: Galleries auto-archive after X days

4. Invoice Generation

Create professional invoices with payment tracking:

csharp
public class Invoice
{
    public Guid Id { get; set; }
    public Guid ClientId { get; set; }
    public string InvoiceNumber { get; set; }
    public DateTime IssueDate { get; set; }
    public DateTime DueDate { get; set; }
    public List<InvoiceItem> Items { get; set; }
    public decimal Subtotal { get; set; }
    public decimal Tax { get; set; }
    public decimal Total { get; set; }
    public InvoiceStatus Status { get; set; }
    public DateTime? PaidAt { get; set; }
}

5. Role-Based Access Control

Different permissions for different team members:

  • Admin: Full access to everything
  • Photographer: Manage their own bookings and clients
  • Editor: Access galleries for post-processing
  • Client: View their own bookings and galleries

Implementation using ASP.NET Core Identity:

csharp
[Authorize(Roles = "Admin,Photographer")]
[HttpPost("bookings")]
public async Task<IActionResult> CreateBooking([FromBody] CreateBookingDto dto)
{
    var result = await _bookingService.CreateBookingAsync(dto);
    return Ok(result);
}

[Authorize(Roles = "Admin")]
[HttpDelete("users/{id}")]
public async Task<IActionResult> DeleteUser(Guid id)
{
    await _userService.DeleteUserAsync(id);
    return NoContent();
}

Technical Highlights

Performance Optimization

I achieved significant performance improvements through:

Database Indexing:

sql
CREATE INDEX idx_bookings_photographer_date 
ON bookings(photographer_id, date)
WHERE status != 'Cancelled';

CREATE INDEX idx_invoices_client_status 
ON invoices(client_id, status);

Query Optimization:

  • Used AsNoTracking() for read-only queries
  • Implemented pagination for large datasets
  • Added eager loading to prevent N+1 queries

Results:

  • 40% faster query response times
  • 60% reduction in database load
  • Smooth performance with 10,000+ records

Security Best Practices

Security was a top priority throughout development:

  • JWT Authentication: Stateless, scalable auth
  • Password Hashing: BCrypt with high cost factor
  • SQL Injection Prevention: Parameterized queries
  • XSS Protection: Content Security Policy headers
  • CORS Configuration: Whitelist trusted origins only
  • Rate Limiting: Prevent brute force attacks

Deployment Strategy

The application deploys in minutes using:

  • Docker containers: Consistent environments
  • Tailscale VPN: Secure remote access
  • PostgreSQL backup: Automated daily backups
  • SSL/TLS: Let's Encrypt certificates
  • Monitoring: Application Insights for telemetry

Lessons Learned

What Worked Well

  1. Clean Architecture: Separating concerns made testing and maintenance easy
  2. TypeScript Everywhere: Catching errors at compile time saved hours
  3. PostgreSQL: Never had performance issues, even with complex queries
  4. Angular Signals: The new reactive system is a game-changer

What I'd Do Differently

  1. Start with Docker: Would have saved setup time for team members
  2. More automated testing: Integration tests would catch regressions earlier
  3. GraphQL instead of REST: Would reduce over-fetching on complex queries
  4. Microservices for galleries: S3 operations could be a separate service

Getting Started

Want to build something similar? Here's my recommended approach:

Phase 1: MVP (2-3 weeks)

  • Client CRUD operations
  • Basic booking system
  • Simple authentication

Phase 2: Core Features (3-4 weeks)

  • Gallery management with S3
  • Invoice generation
  • Email notifications

Phase 3: Polish (2-3 weeks)

  • Advanced search and filtering
  • Reporting and analytics
  • Mobile responsiveness

Tech Stack Recommendations

For Small Teams (1-2 photographers):

  • Backend: .NET Core with SQLite
  • Frontend: Angular or React
  • Hosting: Single VPS or home server

For Growing Businesses (3-10 photographers):

  • Backend: .NET Core with PostgreSQL
  • Frontend: Angular with state management
  • Hosting: Docker containers on cloud VM

For Agencies (10+ photographers):

  • Backend: Microservices architecture
  • Frontend: Micro-frontends
  • Hosting: Kubernetes cluster

Conclusion

Building PhotoManagerAPI taught me that custom software isn't just about writing code—it's about understanding the business problem and crafting a solution that fits perfectly. The combination of .NET Core, Angular, and PostgreSQL proved to be powerful, reliable, and maintainable.

Whether you're building for photographers, consultants, or any service business, the principles remain the same: clean architecture, security first, and always optimize based on real-world usage data.

Key Takeaways:

  • Choose proven technologies over trendy ones
  • Design your database schema carefully upfront
  • Security and performance can't be afterthoughts
  • User feedback drives the best features

Have questions about building a similar system? Feel free to reach out—I love talking about architecture and solving real business problems with code.

Tech Stack:

  • .NET Core 8
  • Angular 18
  • PostgreSQL 16
  • AWS S3
  • Docker
  • Tailscale

Source Code: Available on GitHub (link in my portfolio)

Related Posts

Building with Angular + Firebase? Check out my Photography E-Commerce Platform that combines Firebase auth with Stripe payments and AWS S3 storage.

Self-hosting your projects? Learn how I host production apps on a Raspberry Pi with PM2, Nginx, and Tailscale.

About the Author: Ricardo Gil is a full-stack software engineer specializing in .NET/C#, Angular, and cloud platforms. Read more or subscribe for updates.

Need this built for your business?

I build bilingual (EN/ES) web apps and sites with .NET, Angular and AWS: production-ready, documented and handed off. See Full-Stack Development →

Book a free discovery call.

📬Weekly Newsletter

Get the best home lab & AI content

No spam. One email per week. Unsubscribe anytime.

Share this article