The backstory on AppConnect


@tjsousa

Who am I?

Tiago Sousa.

  • Employee #4 @Talkdesk
  • Platform Tech Lead
  • APIs++
  • (mapcat langs programs)
  • me.fork()

Agenda

  1. Why building a platform?
  2. What exactly did we build?
  3. How did we actually build it?

Why buiding it

Good design is not about making grand plans,
but about taking things apart.

Rich Hickey

Integrations

Scaling

– @aphyr

Platform

  • Business
  • Users
  • Technology

AppConnect

https://developers.talkdesk.com

Partners

Goals

  • Reliability
  • Security
  • Simplicity

Principles

  • Developer Experience (DX)
  • Design by Contracts
  • Productive Teamwork

OpenTalk 2017

What we built

Simplicity is prerequisite for reliability.

Edsger Dijkstra

Reliability

API Gateway

Kong

  • Reverse proxy based on nginx
  • Managed like infra-structure
  • Configuration-based rules

Zuul

  • Standard development methodology
  • More like a library, less configuration
  • First Kotlin system in production

Service Registry

  • Path based rules
  • Templating support
  • Hosted on S3

Rate-limiting

  • Protect upstream services (throttling)
  • Configurable business rules
  • Moving window algorithm

Platform TID

  • Generate UUID if not present and pass through
  • Write in logs/exceptions/APM
  • Background jobs/threads/queues can be tricky
  • Clean code with MDC-pattern and instrumented libs

Challenges

  • Inter-service Communication
    • Eat your own dogfood
    • Overhead and performance
    • Coupled with infra-structure choices
  • Circuit Breaking
    • Avoid the distributed monolith
    • Design microservice split to minimize dependencies
    • Client support circuit breaking

Security

Auth System

  • Custom subset of OAuth functionality
  • Resource owner password credentials
  • Refresh tokens offline mode
  • First Elixir system in production

Talkdesk ID (OpenID Connect)

  • Full OAuth 2.0 flows supported
  • Interactive flows web views
  • OpenID Discovery endpoint
  • Spring Security + Kotlin

JWT

  • Client credentials (RFC7523)
  • API Gateway signed tokens
  • Context information attached

Public key crypto

  • Auto-generated EC key pair
  • Good trade-off between entropy and time
  • Keep us from storing client secrets

SSO

  • Critical part of user experience
  • Design goal for partner launch
  • Full duplex (Partner <-> TD <-> IdP)

Challenges

  • SAML
    • It is a must for enterprise
    • Complex and verbose specs
    • Implementations vary slightly by IDP
  • Legacy
    • PKCS code challenges support (RFC7636)
    • Unified session for all internal apps
    • Some functionality cannot be unlocked yet

Simplicity

Reporting API

  • Built for client access
  • Testbed for ideas and implementation
  • Built on top of data source redesign

Public API

  • Data analysis use-case
  • Enrich with Recordings API
  • Read-only Core APIs
  • App Management APIs

Asynchronicity

  • Resource based long running operations
  • Poll jobs resource & 303 See Other
  • Realtime events through webhooks

Error Messages

  • Consistent and standardized errors
  • Helpful error messages (DX)
  • Problem details JSON object (RFC7807)

Discoverability

  • Swagger documentation
  • Hypermedia links through HAL (Draft)
  • Do not build URLs, follow links (everywhere!)

Challenges

  • IDs
    • BSON vs UUID: what is a good ID?
    • Retrofit with event sourcing is hard
    • Gradual approach with new entities
  • Versioning
    • Accretion is backwards-compatible
    • Turn removing (breaking) into accretion (new names)
    • Make use of lists (links)

Also, has this:

Actions can be created in versions 32.0 and later.

And, this:

These objects have changed in API version 35.0 and affect earlier API versions.

How did we build it

Simple can be harder than complex: You have to work hard to get your thinking clean to make it simple. But it’s worth it in the end because once you get there, you can move mountains.

Steve Jobs

Research

User Story Mapping

  • Discover new use-cases and personas: 11!
  • Collective brain and commitment
  • Celebrate milestones together

Prototype

GraphQL-powered UI

schema {
  query: RootQueryType
  mutation: Mutation
}

type RootQueryType {
  viewer: User
  account: Account
}

type Mutation {
  installApp(appId: ID!, subscriptionId: ID!, licenses: Int!, users: [ID!]!): Installation
  updateAppInstallation(appId: ID!, installationId: ID!, subscriptionId: ID!, licenses: Int!, users: [ID!]!): Installation
  uninstallApp(appId: ID!, installationId: ID!, reason: String): Installation
}
query GetApp($appId: ID!) {
  account {
    app(id: $appId) {
      id
      displayName
      icon: resource(type: ICON) {
        url
      }
      ...SubscriptionInfo
      ...AuthorizationInfo
    }
    billing {
      isTrial
    }
  }
}

Swagger pipeline

  • API specs as code
  • Pull request reviews as gatekeeper
  • Quick protyping tool

Documentation

  • Reference
  • Guides
  • Code samples

Contracts

  • Contract based testing
  • Parallel development
  • Painless integration

Communicate

  • Engineering / scrum of scrums
  • Product / sprints
  • Management / demos

Quality Assurance

  • Deploy often (feature flags)
  • GraphiQL & Paw (tooling)
  • Appinator (dogfooding)

Observability

  • Load testing
  • Performance testing
  • Resilience testing

Developer Experience

  • Onboarding sessions
  • Technical support
  • Partner feedback

OAuth was simple to integrate and responsiveness very good. Very pleasant experience. – Omniquo

APIs are pretty straight forward and snippets were useful. Onboarding process was fine. – Simple Emotion

Self-service

Developer Portal

Thank you,

team!